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

标签 python c dll ctypes

我很清楚 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

以及定义.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;
}

然后我将其构建到一个 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()

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

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

第二行返回 None 而不是 9.9。然后我尝试了另一种方法,将这一行放在 shell 中:

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

这条线返回了一个不足为奇的 9.9,但与最后一个结果 None 相比令人惊讶。这两行不应该相同吗?我决定在 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)

所有这些行最终返回 9.9。如果导入 trialDLL3.py 模块,这些行是否与这两行相同?

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

如果它们是同一笔交易,为什么两行类版本返回 None 而显式方式返回预期的 9.9?提前致谢!

最佳答案

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

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

关于Python,使用 ctypes 创建 C++ 类包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16268140/

相关文章:

windows - 在 Windows XP 上使用 cpprestsdk 编译的 dll 库

visual-studio - 如何让 Visual Studio 将 DLL 文件复制到输出目录?

python - 计算 sympy 中向量的 x 分量

python - 如何在OpenCV中找到两个轮廓之间的最近点

c - 从外部文件访问链接列表

C 编程 : Scanf in while loop only reads input once and then terminates

c++: 使用 Visual Basic dll

Python:从 Web 界面运行时导入其他 python 文件

python - 重新索引堆叠的 DataFrame

c - 模拟绘画应用的笔触