Python ctypes:在Mac上使用lib.so时修改指针地址,但在Windows上使用lib.dll时不修改指针地址 来源 C++ /***为外部“C”键入定义类模板***/ typedef Mpoly mpolydough; //将函数声明为ctypes的外部
ctypes:在Mac上使用lib.so时修改指针地址,但在Windows上使用lib.dll时不修改指针地址 来源 C++Python ctypes:在Mac上使用lib.so时修改指针地址,但在Windows上使用lib.dll时不修改指针地址 来源 C++ /***为外部“C”键入定义类模板***/ typedef Mpoly mpolydough; //将函数声明为ctypes的外部,python,c++,windows,macos,ctypes,Python,C++,Windows,Macos,Ctypes,ctypes:在Mac上使用lib.so时修改指针地址,但在Windows上使用lib.dll时不修改指针地址 来源 C++ /***为外部“C”键入定义类模板***/ typedef Mpoly mpolydough; //将函数声明为ctypes的外部“C” // //>>编译器语句(mac/linux):g++-shared-o libPoly.so-fPIC libPoly.cpp //>>编译器语句(windows):g++-shared-o libPoly.dll libPoly.c
/***为外部“C”键入定义类模板***/
typedef Mpoly mpolydough;
//将函数声明为ctypes的外部“C”
//
//>>编译器语句(mac/linux):g++-shared-o libPoly.so-fPIC libPoly.cpp
//>>编译器语句(windows):g++-shared-o libPoly.dll libPoly.cpp
//
外部“C”{
/***libPoly构造函数/析构函数例程***/
mpolydoull*Poly_new(int size,int dim){返回new(nothrow)mpolydoull(size,dim);}
void Poly_del(mpolydoull*foo){delete foo;}
/***libPoly杂项例程***/
无效多打印(MpolyDouble*foo){
//对象指针的打印输出地址
STD::CUT这是我的最终解决方案。我对事物的C++方面没有做任何重大的改变——只有Python cType绑定。我还添加了一些逻辑来处理动态库(共享对象)的导入。,这不是通用的。它适用于我的两个工作站和其他一些我必须协作的工作站,但Python2.7的32位版本除外
经验教训:
- 在使用不同平台(Unix与Windows、32位与64位等)时,请注意数字的默认位长度
- 利用类属性为:(i)良好的编码实践,(ii)确保<>代码>γ-DELYX例程可以容易地链接到C++对象的析构函数例程,这在将对象作为指针来回传递时是必不可少的。
- 我犯了一个错误,把
lib
作为一个全局调用,直到调用\uu del\uuu
才给我带来问题;然而,当调用lib.Poly\u del(self.obj)
时,lib
不再定义
Python绑定(PolyWrapper.py)
它应该是lib.Poly\u del.argtypes=[c\u void\u p]
,而不是lib.Poly\u del.argtype=c\u void\u p
。还有id(self.obj)
与C所看到的任何东西都无关。在CPython中,这是Python对象的地址,它只是一个Pythonint
,因为C\u void\u p
getfunc转换指针值。为什么这对Poly\u del argtypes很重要?另外,关于id(self.obj),我同意你的看法不与C相关,如我所发现的!<代码>自已.Obj/<代码>是C++对象的地址,作为Python整数。如果你不设置<代码> AgType < /代码>,它使用默认转换为C <代码> int >代码>,它将指针截断为32位值。如果你不想设置<代码> AgStase< /Cord>,尽管我建议你这样做,然后你需要将指针值包装为self.obj=c\u void\u p(lib.Poly\u new(size,dim))
\uuu del\uuu
不应引用全局变量,因为它们在解释器拆卸过程中被清除。作为一种解决方法,您可以添加一个\u lib
类属性和引用self.\u lib
或仅使用默认参数值的本地引用:定义\uu del\uu(self,Poly\u del=lib.Poly\u del)
。我还将添加一个class属性\u obj=None
。然后在\uuu init\uuuu
中,分配self.\u obj
(注意:下划线),它覆盖类属性。然后在中,如果self,则仅调用Poly\u del
。\u obj不是None
,并执行del self.\u obj
以恢复None的类属性值。
/*** type define class template for extern "C" ***/
typedef Mpoly<double> MpolyDouble;
// Declare functions as extern "C" for ctypes
//
// >> compiler statement (mac/linux): g++ -shared -o libPoly.so -fPIC libPoly.cpp
// >> compiler statement (windows): g++ -shared -o libPoly.dll libPoly.cpp
//
extern "C" {
/*** libPoly Constructor/Destructor Routines ***/
MpolyDouble* Poly_new(int size, int dim) { return new(nothrow) MpolyDouble(size,dim); }
void Poly_del(MpolyDouble* foo) { delete foo; }
/*** libPoly Miscellaneous Routines ***/
void PolyPrint(MpolyDouble* foo) {
// print out address of object pointer
std::cout << "address of foo: " << foo << std::endl;
// call MpolyDouble.print() method
foo->print();
}
}
#*** import python libraries ***#
from ctypes import *
from numpy.ctypeslib import ndpointer
import numpy as np
import weakref
#**************************************#
#*** load the libPoly shared object ***#
#**************************************#
lib = CDLL('./libPoly.so') #! for Mac/Linux
#lib = CDLL('./libPoly.dll') #! for Windows
#********************************************************#
#*** set the argument types for each member attribute ***#
#********************************************************#
## Poly_new
lib.Poly_new.argtypes = [c_int, c_int]
lib.Poly_new.restype = c_void_p
## Poly_del
lib.Poly_del.argtypes = [c_void_p] #<---edit
lib.Poly_del.restype = None
## PolyPrint
lib.PolyPrint.argtypes = [c_void_p] #<---edit
lib.PolyPrint.restype = None
#********************************************************#
#*** define a python class Poly ***#
#********************************************************#
class Poly(object):
# GHV Instantiation Routine:
def __init__(self,size=1,dim=2):
# ensure that the input args are of correct type
size = int(size)
dim = int(dim)
# call the C/C++ function
self.obj = lib.Poly_new(size,dim)
def __del__(self):
lib.Poly_del(self.obj)
self._obj = None
# GHV Print Routine:
def Print(self):
print 'address of self.obj',hex(id(self.obj))
# call the C/C++ function
lib.PolyPrint(self.obj)
#*************************************#
#*** import python libraries ***#
#*************************************#
from ctypes import *
from numpy.ctypeslib import ndpointer
import numpy as np
import weakref
import platform
#**************************************#
#*** load the libPoly shared object ***#
#**************************************#
print.system()
if (platform.system() == "Windows" or platform.system() == "CYGWIN-6.1"):
lib = CDLL('./libPoly.dll')
else:
lib = CDLL('./libPoly.so')
#********************************************************#
#*** set the argument types for each member attribute ***#
#********************************************************#
## Poly_new
lib.Poly_new.argtypes = [c_int, c_int]
lib.Poly_new.restype = c_void_p
## Poly_del
lib.Poly_del.argtypes = [c_void_p]
lib.Poly_del.restype = None
## PolyPrint
lib.PolyPrint.argtypes = [c_void_p]
lib.PolyPrint.restype = None
#********************************************************#
#*** define a python class Poly ***#
#********************************************************#
class Poly(object):
_obj = None
_local = lib
# Poly Instantiation Routine:
def __init__(self,size=1,dim=1):
# ensure that the input args are of correct type
size = int(size)
dim = int(dim)
# call the C/C++ function
self._obj = c_void_p(self._lib.Poly_new(size,dim))
# Poly Destructor Routine:
def __del__(self):
if (self._obj is not None):
self._lib.Poly_del(self._obj)
del self._obj
# Poly Print Routine:
def Print(self):
# call the C/C++ function
self._lib.PolyPrint(self._obj)