Python ctypes:在Mac上使用lib.so时修改指针地址,但在Windows上使用lib.dll时不修改指针地址 来源 C++ /***为外部“C”键入定义类模板***/ typedef Mpoly mpolydough; //将函数声明为ctypes的外部

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

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.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对象的地址,它只是一个Python
int
,因为
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)