【问题标题】:Python Ctypes read char* returned from C++ dllPython Ctypes 读取从 C++ dll 返回的 char*
【发布时间】:2018-02-13 13:40:14
【问题描述】:

我正在发现 ctypes 的世界,因为我正在 Windows 上用 C++ 编写一个 DLL,并带有一个 C 包装器,以便能够在 Python 上使用它。当我从 C++ 函数返回例如 char * 时,我不明白它如何与 Python 上的指针一起工作,如何在指针的地址获取数据?

myClass.h文件:

#include "myClassInc.h"
class __declspec(dllexport) myClass// __declspec to generate .lib file
{
public:
    // Attributes
    char * name;

    // Methods
    myClass();
    ~myClass();

    bool myMethod(string);
};

myClassInc.h(C 封装):

#ifdef MYCLASS
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __declspec(dllimport)
#endif

// Wrapper in C for others languages (LabVIEW, Python, C#, ...)
extern "C"
{
    EXPORT typedef struct myClass myClass; // make the class opaque to the wrapper
    EXPORT myClass* cCreateObject(void);
    EXPORT char* cMyMethod(myClass* pMyClass);
}

myClass.cpp

#include "myClass.h"

myClass::myClass() {}
myClass::~myClass() {}

bool myClass::myMethod(string filename_video)
{
    int iLength = filename_video.length();
    name = new char[iLength+1];
    strcpy(name, filename_video.c_str());
    return true;
}

myClass* cCreateObject(void)
{
    return new myClass();
}

char * cMyMethod(myClass* pMyClass)
{
    if (pMyClass->myMethod("hello world"))
        return pMyClass->name;
}

终于pythonScript.py

from ctypes import *

mydll = cdll.LoadLibrary("mydll.dll")
class mydllClass(object):
    def __init__(self):
        mydll.cCreateObject.argtypes = [c_void_p]
        mydll.cCreateObject.restype = c_void_p

        mydll.cMyMethod.argtypes = [c_void_p]
        mydll.cMyMethod.restype = POINTER(c_char_p)

        self.obj = mydll.cCreateObject("")

    def myMethod(self):
        return mydll.cMyMethod(self.obj)

f = mydllClass() # Create object
a = f.myMethod() # WANT HERE TO READ "HELLO WORLD"

a 中的结果是<__main__.LP_c_char_p object at 0x0000000002A4A4C8>

我没有在 ctypes 文档中找到如何读取这样的指针数据。你能帮帮我吗?

如果我想从 Python 将一个 char * 传递给 myDll,将会出现同样的问题,如何做到这一点(通常在 dll 中提供要从 Python 读取的文件的路径)。

【问题讨论】:

    标签: python c++ ctypes


    【解决方案1】:

    c_char_pchar*POINTER(c_char_p)char**。修复你的.restype,你应该会很好。 ctypes 具有将 c_char_p 转换为 Python 字节字符串的默认行为。

    另外,mydll.cCreateObject.argtypes = None 对于没有参数是正确的。现有定义指出 void* 是必需参数。

    【讨论】:

    • 如果我取消POINTER,程序会因Process finished with exit code -1073741819 (0xC0000005) 而崩溃(完全是Python)。当我拨打myMethod 时发生崩溃。我测试返回一个整数或布尔值,它正在工作。所以问题只出在 char* 上。
    • @MathieuGauquelin 提供的示例无法按原样编译(例如,缺少 #include <string>)。修复错误并删除 POINTER 后,它对我有用。您必须将代码更新为与您测试过的完全相同。也提供相关的环境细节。我使用的是 Windows 10、VS2015 和 Python 3.6(均为 64 位)。
    • 它正在工作;)谢谢!我也成功地使用c_char_p("mystring".encode('utf-8')) 发送了一个字符串。下一步,得到一个 unsigned short 的双指针:D
    • @Mathieu b'hello' 是如何发送字节串。你不需要包裹在 c_char_p 中。
    猜你喜欢
    • 2013-12-26
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多