使用 Ctypes 将C++代码嵌入到 Python 中 (SpecialKEval)

Embed C++ code into Python with Ctypes (SpecialKEval)

本文关键字:Python SpecialKEval Ctypes C++ 代码 使用      更新时间:2023-10-16

我正在编写一个Python应用程序,我需要能够从文件SevenEval.cpp项目中调用C++函数getRankOfSeven 来自项目SpecialKEval。出于明显的性能原因,我必须运行 SpecialKEval 的 C++ 版本而不是 python 版本,因为我的应用程序的重点是计算获胜概率的蒙特卡罗模拟。

我已经编译了这些文件:

g++ -o SevenEval.so -shared -fPIC FiveEval.cpp SevenEval.cpp

并将输出导入 Python:

from ctypes import cdll
se = cdll.LoadLibrary('./SevenEval.so')

这加载没有问题,但se.SevenEval()抛出AttributeError: ./SevenEval.so: undefined symbol: SevenEval

我已经读到为了让 ctypes 工作,我需要有 C 对象/函数而不是C++对象/函数,并且用 extrect "C" { 包装它们,但我不知道任何 C/C++(我只用 Python 编码),所以我不知道该怎么做,而且示例太简单了,无法适应我的问题。

在询问之前我已经搜索了很多,也许解决方案就在那里,但由于我的 C/C++ 水平低,我不知道该怎么做。如果有人能给我一些指导方针,详细的例子,或者为我做这件事,我会很高兴。

注意:运行在 Ubuntu 13.10 64 位,Python 2.7


在 Smoothware 评论后编辑。

好的,这是函数在 SevenEval.h 上的声明: short getRankOfSeven(const int CARD1, const int CARD2, const int CARD3, const int CARD4, const int CARD5, const int CARD6, const int CARD7);

这是我在文件末尾添加的内容:

extern "C" {
  SevenEval* SevenEval_new(){ return new SevenEval(); }
  short SevenEval_getRankOfSeven(SevenEval* foo, const int CARD1, const int CARD2, const int CARD3, const int CARD4, const int CARD5, const int CARD6, const int CARD7){ foo->getRankOfSeven(CARD1, CARD2, CARD3, CARD4, CARD5, CARD6, CARD7);}
}

这是我的Python文件:

from ctypes import cdll
lib = cdll.LoadLibrary('./SevenEval.so')
class SevenEval(object):
    def __init__(self):
        self.obj = lib.SevenEval_new()
    def getRankOfSeven(self, c1, c2, c3, c4, c5, c6, c7):
        lib.SevenEval_getRankOfSeven(self.obj, c1, c2, c3, c4, c5, c6, c7)

se = SevenEval() # Runs OK
print se.getRankOfSeven(1,2,3,4,5,6,7) # Gives Segmentation fault (core dumped)

我做错了什么?

上次编辑中的解决方案适用于 32 位 Python。对于 64 位:

from ctypes import cdll
from ctypes import c_void_p
lib = cdll.LoadLibrary('./SevenEval.so')
lib.SevenEval_new.restype = c_void_p

class SevenEval(object):
    def __init__(self):
        self.obj = c_void_p(lib.SevenEval_new())
    def getRankOfSeven(self, c1, c2, c3, c4, c5, c6, c7):
        return lib.SevenEval_getRankOfSeven(
        self.obj, c1, c2, c3, c4, c5, c6, c7)