简体   繁体   English

Python Ctypes 读取从 C++ dll 返回的 char*

[英]Python Ctypes read char* returned from C++ dll

I am discovering the world of ctypes because I am writing a DLL in C++ on Windows with a C wrapper to be able to use it on Python for example.我正在探索 ctypes 的世界,因为我正在 Windows 上用 C++ 编写一个带有 C 包装器的 DLL,以便能够在 Python 上使用它。 I don't understand how it works with pointer on Python when I return for example a char * from my C++ function, how to get the data at the adress of the pointer ?当我从 C++ 函数返回例如 char * 时,我不明白它如何处理 Python 上的指针,如何获取指针地址处的数据?

myClass.h file: 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 wrapper) : 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);
}

and myClass.cpp :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;
}

Finally pythonScript.py :最后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"

The result in a is <__main__.LP_c_char_p object at 0x0000000002A4A4C8> . a 中的结果是<__main__.LP_c_char_p object at 0x0000000002A4A4C8>

I don't find on the ctypes documentation how to read the data of a pointer like this.我没有在 ctypes 文档中找到如何读取这样的指针数据。 Can you help me please?你能帮我吗?

The same question will follow if I want to pass from Python a char * to myDll, how to do this (typically to give at the dll the path of a file to read from Python).如果我想从 Python 传递一个 char * 到 myDll,将出现同样的问题,如何做到这一点(通常是在 dll 中提供从 Python 读取的文件路径)。

c_char_p is a char* . c_char_p是一个char* POINTER(c_char_p) is a char** . POINTER(c_char_p)是一个char** Fix your .restype and you should be good.修复你的.restype ,你应该很好。 ctypes has a default behavior of converting a c_char_p to a Python byte string. ctypes具有将c_char_p转换为 Python 字节字符串的默认行为。

Also, mydll.cCreateObject.argtypes = None is correct for no arguments.此外, mydll.cCreateObject.argtypes = None对于没有参数是正确的。 The existing definition states a void* is a required parameter.现有定义指出void*是必需参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM