Python,使用ctypes创建c++类包装器。

时间:2021-07-14 22:28:18

I'm well aware that there is no standard ABI for c++, so this is what I did:

我很清楚c++没有标准的ABI,所以我这样做了:

//trialDLL.h
#ifndef TRIALDLL_H_
#define TRIALDLL_H_

class MyMathFuncs
{
private:
    double offset;

public:
    MyMathFuncs(double offset);

    ~MyMathFuncs();

    double Add(double a, double b);

    double Multiply(double a, double b);

    double getOffset();
};

#ifdef __cplusplus
extern "C"{
#endif

#ifdef TRIALDLL_EXPORT
#define TRIALDLL_API __declspec(dllexport)
#else
#define TRIALDLL_API __declspec(dllimport)
#endif

    TRIALDLL_API MyMathFuncs* __stdcall new_MyMathFuncs(double offset);

    TRIALDLL_API void __stdcall del_MyMathFuncs(MyMathFuncs *myMath);

    TRIALDLL_API double __stdcall MyAdd(MyMathFuncs* myMath, double a, double b);


#ifdef __cplusplus
}
#endif

#endif

And the definition .cpp: (Other class functions' definitions are omitted)

和定义。cpp:(省略其他类函数的定义)

//trialDLL.cpp
#include "trialDLL.h"

MyMathFuncs* __stdcall new_MyMathFuncs(double offset)
{
return new MyMathFuncs(offset);
}


void __stdcall del_MyMathFuncs(MyMathFuncs *myMath)
{
    myMath->~MyMathFuncs();
}


double __stdcall MyAdd(MyMathFuncs *myMath, double a, double b)
{
return myMath->Add(a, b);
}

// class functions
double MyMathFuncs::Add(double a, double b)
{
return a+b+ this->offset;
}

And I build this into a dll and named it trialDLL3.dll. Then in python, I wrote a module as:

我将它构建到一个dll中并命名为trialDLL3.dll。然后在python中,我编写了一个模块:

#trialDLL3.py
import ctypes
from ctypes import WinDLL

class MyMath(object):
    def __init__(self, offset):
        self.FunMath = WinDLL('trialDLL3.dll')
        self.FunMath.new_MyMathFuncs.argtypes = [ctypes.c_double]
        self.FunMath.new_MyMathFuncs.restype = ctypes.c_void_p

        self.FunMath.MyAdd.argtypes = [ctypes.c_void_p, \
                                       ctypes.c_double, ctypes.c_double]
        self.FunMath.MyAdd.restype = ctypes.c_double

        self.obj = self.FunMath.new_MyMathFuncs(offset)

    def FunAdd(self, a, b):
        self.FunMath.MyAdd(self.obj, a, b)

    def delete(): 
        self.FunMath.del_MyMathFuncs()

After all these, strange things happened. In the IDLE python shell, I did:

在这一切之后,奇怪的事情发生了。在空闲的python shell中,我这样做了:

theMath = MyMath(3.3)        #create the instance
theMath.FunAdd(3.3, 3.3)     #call the function

The second line returned None instead of 9.9. Then I tried another way round, putting this line in the shell:

第二行返回None,而不是9.9。然后我尝试了另一种方法,把这条线放在壳里:

theMath.FunMath.MyAdd(theMath.obj, 3.3 ,3.3)

And this line returns me an unsurprising 9.9, but surprising when compared to the last result None. Shouldn't these two lines identical? And I decided to run all those lines explicitly in python shell and see what can go wrong, writing: (excluding the imports)

这条线返回给我的是9。9,这并不令人惊讶,但与最后一个结果相比,结果为0。这两行不应该是一样的吗?我决定用python shell显式地运行所有这些行,看看会出现什么问题,写:(不包括导入)

loadedDLL = WinDLL('trialDLL3.dll')
loadedDLL.new_MyMathFuncs.argtypes = [ctypes.c_double]
loadedDLL.new_MyMathFuncs.restype = ctypes.c_void_p
loadedDLL.MyAdd.argtypes = [ctypes.c_void_p, \
                                    ctypes.c_double, ctypes.c_double]
loadedDLL.MyAdd.restype = ctypes.c_double
obj = loadedDLL.new_MyMathFuncs(3.3)
FunMath.MyAdd(obj, 3.3, 3.3)

All these lines finally returned 9.9. Aren't these lines identical to the two lines if the trialDLL3.py module is imported?

所有这些行最终返回9.9。如果是trialDLL3,这两条线不是完全相同的吗?py模块是进口的吗?

theMath = MyMath(3.3)        #create the instance
theMath.FunAdd(3.3, 3.3)     #call the function

If they are the same deal, why the two line class version returns None and the explicit way return expected 9.9? Thanks in advance!

如果它们是相同的,为什么两行类版本返回None,而显式方式返回9.9?提前谢谢!

1 个解决方案

#1


5  

Everything works fine... but you forgot to pass along the return value of the C function in the method MyMath.FunAdd!

一切都好…但是您忘记了在MyMath.FunAdd方法中传递C函数的返回值!

def FunAdd(self, a, b):
    return self.FunMath.MyAdd(self.obj, a, b)
    ^^^^^^

#1


5  

Everything works fine... but you forgot to pass along the return value of the C function in the method MyMath.FunAdd!

一切都好…但是您忘记了在MyMath.FunAdd方法中传递C函数的返回值!

def FunAdd(self, a, b):
    return self.FunMath.MyAdd(self.obj, a, b)
    ^^^^^^