更新在C DLL中创建的LP_c_ubyte缓冲区 [英] Updating an LP_c_ubyte buffer created in a C DLL

查看:278
本文介绍了更新在C DLL中创建的LP_c_ubyte缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am creating a Python wrapper for a C DLL using Python ctypes.

在下面的Python代码中,我创建了 c_ubyte connectionString c $ c>我需要填写个人。例如1,2,3,4,5,6 ...此连接字符串将传递到DLL的 DoCallBack 函数并进行打印。创建一个缓冲区以供回调函数填充,并将所有内容传递给python回调函数。

In the Python code below I am creating a array connectionString of c_ubyte that I need to fill int the individual. For example 1,2,3,4,5,6... This connection string is passed to the DLL's DoCallBack function and printed. A buffer is created for the callback function to fill in and everything is passed to the python call back function.


  1. 我正在寻找一种在将 connectionString 字节传递给之前将其更新的方法DLL的 DoCallBack

  2. 然后如何从python callbackFnk 中的 connectionString 中提取字节功能。

  3. 我正在寻找一种从 callbackFnk outBuffer 中字节的方法c> python函数

  1. I am looking for a way to update the connectionString bytes before passing them to the DLL's DoCallBack.
  2. Then how to extract the bytes from the connectionString in the python callbackFnk function.
  3. I am looking for a way to update the bytes in outBuffer from the callbackFnk python function

此问题的延续
在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) 


推荐答案

OP的示例存在许多错误,并且无法编译,因此我将其组合在一起。我假设 connectionString 只是一个以nul结尾的输入字符串,并演示在回调中更新输出字符串。

The OP's example has a number of errors and doesn't compile, so I put this together. I assume connectionString is just a nul-terminated input string, and demonstrate updating the output string in the callback.

注意使用 input 字符串, c_char_p 可以是类型,并且可以传递Python字节字符串。 c_wchar_p 用于Python Unicode字符串。该字符串不得在C代码中修改。回调也会将其作为Python字符串接收,从而使其易于阅读。

Note with an input string, c_char_p can be the type and a Python byte string can be passed. c_wchar_p is used for Python Unicode strings. The string must not be modified in the C code. The callback will receive it as a Python string as well, making it easy to read.

输出缓冲区只能被索引,请注意不要索引超出长度缓冲区。调用者分配的输出缓冲区应始终作为指针和长度传递。

The output buffer can just be indexed, being careful to not index past the length of the buffer. Output buffers allocated by the caller should always be passed as a pointer-and-length.

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]

这篇关于更新在C DLL中创建的LP_c_ubyte缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆