更新在 C DLL 中创建的 LP_c_ubyte 缓冲区

Updating an LP_c_ubyte buffer created in a C DLL

我正在使用 Python ctypes 为 C DLL 创建一个 Python 包装器。

在下面的 Python 代码中,我创建了一个 connectionStringc_ubyte 数组,我需要用它来填充个人。例如 1,2,3,4,5,6... 这个连接字符串被传递给 DLL 的 DoCallBack 函数并打印出来。为回调函数创建一个缓冲区来填充,并将所有内容传递给 python 回调函数。

  1. 我正在寻找一种方法来更新 connectionString 字节,然后再将它们传递给 DLL 的 DoCallBack
  2. 然后如何从pythoncallbackFnk函数中提取connectionString的字节。
  3. 我正在寻找一种方法来从 callbackFnk python 函数
  4. 中更新 outBuffer 中的字节

这个问题的延续

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) 

OP的例子有很多错误,无法编译,所以我把它放在一起。我假设 connectionString 只是一个以 nul 结尾的输入字符串,并演示了在回调中更新输出字符串。

请注意,对于 输入 字符串,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]