小编典典

使用 CType 从类中调用函数

all

我试图从一个类中调用一个函数,据我所知,你只是按预期调用“object.class.function”是正确的,还是我做错了什么?

图书馆.c

#include <stdio.h>
#include "clibrary.h"

void Clibrary::prompt()
{
    printf("hello world\n");
}

图书馆.h

class Clibrary
{
public:
    Clibrary(){};
    ~Clibrary(){};
    static void prompt();
};

然后构建它

g++ -fPIC -shared -o clibrary.so cLibrary.c

然后测试它是否有正确的符号

$ nm -gDC clibrary.so 
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U puts
000000000000111a T Clibrary::prompt()

然后在 test.py 中使用 CTypes 调用它。

#!/usr/bin/python3
import ctypes

libObject = ctypes.CDLL('./clibrary.so')
libObject.Clibrary.prompt()

然后尝试运行它

./test.py 
Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    libObject.Clibrary.prompt()
  File "/usr/lib/python3.8/ctypes/__init__.py", line 386, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.8/ctypes/__init__.py", line 391, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: ./clibrary.so: undefined symbol: Clibrary

没有堆栈溢出调节器:它不像使用 ctypes 从 python 调用 C 函数,因为它在一个类中。


阅读 91

收藏
2022-07-06

共1个答案

小编典典

ctypes了解 C 链接并键入通常需要创建extern "C"包装函数的 C 库。在这种特殊情况下,您可以强制ctypes为静态方法加载名称修饰的 C 符号,但不建议这样做。

这里都展示了:

test.cpp

#include <stdio.h>

#ifdef _WIN32
#   define API __declspec(dllexport)  // Windows requires explicit export of functions.
#else
#   define API
#endif

class API Clibrary  // exported to see name decoration, but not needed
{
public:
    Clibrary() {};
    ~Clibrary() {};
    static void prompt() { printf("hello world\n"); }
};

// wrapper function with C linkage
extern "C" API void prompt() { Clibrary::prompt(); }

从 DLL 导出的符号列表:

ordinal hint RVA      name

      1    0 00001020 ??0Clibrary@@QEAA@XZ
      2    1 00001030 ??1Clibrary@@QEAA@XZ
      3    2 00001040 ??4Clibrary@@QEAAAEAV0@AEBV0@@Z
      4    3 00001050 ?prompt@Clibrary@@SAXXZ
      5    4 00001000 prompt

test.py

import ctypes

libObject = ctypes.CDLL('./test')

# Hack but works.  Decorated name is not standard and could
# be different using a different compiler.
other = getattr(libObject,'?prompt@Clibrary@@SAXXZ')
other()

libObject.prompt()                                    # best

输出:

hello world
hello world
2022-07-06