Обновление буфера LP_c_ubyte, созданного в C DLL - PullRequest
0 голосов
/ 26 апреля 2018

Я создаю оболочку Python для C DLL, используя Python ctypes.

В приведенном ниже коде Python я создаю массив connectionString из c_ubyte, который мне нужно заполнить в отдельности. Например, 1,2,3,4,5,6 ... Эта строка подключения передается в функцию DLL DoCallBack и печатается. Для заполнения функции обратного вызова создается буфер, и все передается в функцию обратного вызова python.

  1. Я ищу способ обновить connectionString байты перед передачей их в DLL DoCallBack.
  2. Тогда как извлечь байты из connectionString в функции python callbackFnk.
  3. Я ищу способ обновить байты в outBuffer из функции callbackFnk python

продолжение этого вопроса Как в Python установить значение 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) 

1 Ответ

0 голосов
/ 27 апреля 2018

Пример 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]
...