我正在使用Python ctypes为C DLL创建一个Python包装器。
在下面的Python代码中,我创建了一个connectionString
的数组c_ubyte
,我需要填充个人。例如1,2,3,4,5,6 ...此连接字符串将传递给DLL的DoCallBack
函数并打印。为回调函数创建一个缓冲区以填充,并将所有内容传递给python回调函数。
connectionString
字节,然后再将它们传递给DLL的DoCallBack
。 connectionString
函数中的callbackFnk
中提取字节。 outBuffer
python函数中的callbackFnk
中的字节这个问题的延续 In python how do I set the value of a LP_c_ubyte
C DLL代码
typedef void(*FPCallback)(unsigned char * outBuffer, unsigned short MaxOutBufferLength, unsigned char * connectionString);
FPCallback g_Callback;
extern "C" __declspec( dllexport ) void RegisterCallback(void(*p_Callback)( unsigned char * outBuffer, unsigned short MaxOutBufferLength, unsigned char * connectionString)) {
g_Callback = p_Callback ;
}
extern "C" __declspec( dllexport ) void DoCallBack( unsigned char connectionString) {
printf( "connectionString=[%02x %02x %02x %02x %02x %02x...]\n", connectionString[0], connectionString[1], connectionString[2], connectionString[3], connectionString[4], connectionString[5] );
const unsigned short MAX_BUFFER_SIZE = 6 ;
unsigned char outBuffer[MAX_BUFFER_SIZE];
g_Callback( outBuffer, MAX_BUFFER_SIZE, connectionString, 6 );
// Print the results.
printf( "buffer=[%02x %02x %02x %02x %02x %02x...]\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5] );
}
Python代码
def callbackFnk( outBuffer, outBufferMaxSize, connectionString )
# (Q2) How do I extract individual bytes of the connectionString?
# (Q3) How do I update individual bytes of the out buffer?
customDLL = cdll.LoadLibrary ("customeDLL.dll")
# RegisterCallback
CustomDLLCallbackFUNC = CFUNCTYPE(None, POINTER( c_ubyte), c_ushort, POINTER( c_ubyte) )
CustomDLLCallback_func = CustomDLLCallbackFUNC( callbackFnk )
RegisterCallback = customDLL.RegisterCallback
RegisterCallback.argtypes = [ CustomDLLCallbackFUNC ]
RegisterCallback( CustomDLLCallback_func )
# DoCallBack
DoCallBack = customDLL.DoCallBack
DoCallBack.argtypes = [ POINTER( c_ubyte) ]
connectionString = c_ubyte(6)
# (Q1) How do I update this array of bytes?
# Call the callback
DoCallBack(connectionString)
答案 0 :(得分:1)
OP的例子有很多错误而且没有编译,所以我把它放在一起。我假设connectionString
只是一个以空终止的输入字符串,并演示更新回调中的输出字符串。
注意 input 字符串,c_char_p
可以是类型,并且可以传递Python字节字符串。 c_wchar_p
用于Python Unicode字符串。不得在C代码中修改字符串。回调函数也会将它作为Python字符串接收,使其易于阅读。
输出缓冲区只能被索引,小心不要索引超过缓冲区的长度。调用者分配的输出缓冲区应始终作为指针和长度传递。
C ++ DLL
#include <stdio.h>
typedef void (*CALLBACK)(const char* string, unsigned char* buffer, size_t size);
CALLBACK g_pCallback;
extern "C" __declspec(dllexport) void RegisterCallback(CALLBACK pCallback) {
g_pCallback = pCallback;
}
extern "C" __declspec(dllexport) void DoCallBack(char* string) {
unsigned char buf[6];
printf("string = %s\n", string);
g_pCallback(string, buf, sizeof(buf));
printf("buf = [%02x %02x %02x %02x %02x %02x]\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
}
<强>的Python 强>
from ctypes import *
CALLBACK = CFUNCTYPE(None,c_char_p,POINTER(c_ubyte),c_size_t)
@CALLBACK
def callback(string,buf,length):
print(string)
for i in range(length):
buf[i] = i * 2
dll = CDLL('test')
# RegisterCallback
RegisterCallback = dll.RegisterCallback
RegisterCallback.argtypes = [CALLBACK]
RegisterCallback.restype = None
RegisterCallback(callback)
# DoCallBack
DoCallBack = dll.DoCallBack
DoCallBack.argtypes = [c_char_p]
DoCallBack.restype = None
DoCallBack(b'test string')
<强>输出强>
string = test string
b'test string'
buf = [00 02 04 06 08 0a]