Reputation: 625
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. 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 ?
myClass.h
file:
#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) :
#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
:
#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
:
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>
.
I don't find on the ctypes documentation how to read the data of a pointer like this. 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).
Upvotes: 1
Views: 2274
Reputation: 177471
c_char_p
is a char*
. POINTER(c_char_p)
is a char**
. Fix your .restype
and you should be good. ctypes
has a default behavior of converting a c_char_p
to a Python byte string.
Also, mydll.cCreateObject.argtypes = None
is correct for no arguments. The existing definition states a void*
is a required parameter.
Upvotes: 3