简体   繁体   English

使用char缓冲区从DLL创建C函数的python回调。

[英]Creating a python callback for a C function from a DLL with a char buffer.

I am trying to create a python wrapper for a C DLL. 我正在尝试为C DLL创建一个python包装器。 The C DLL uses a callbacks to "send" messages via UDP from the DLL. C DLL使用回调来通过UDP从DLL“发送”消息。

What I expected to happen was that python code would load the DLL library and the two functions. 我期望发生的是python代码将加载DLL库和两个函数。 Then it would register the call back with the DLL using the RegisterCallbackSendMessage function. 然后它将使用RegisterCallbackSendMessage函数向DLL RegisterCallbackSendMessage回调。 The pointer to the callback would be stored in memory in the DLL memory space. 指向回调的指针将存储在DLL存储空间的内存中。 Then the python code would call the SendWhoIs DLL function. 然后python代码将调用SendWhoIs DLL函数。 This function would create a buffer and use the SendMessage function pointer to send the message from the DLL to the python code. 此函数将创建一个缓冲区并使用SendMessage函数指针将消息从DLL发送到python代码。

The issue I am having is that the message parameter in the SendMessage function in python doesn't know how to interpreter a void * and I can not pass this buffer to sock.sendto function. 我遇到的问题是python中的SendMessage函数中的message参数不知道如何解释void *并且我无法将此缓冲区传递给sock.sendto函数。

I get the following error. 我收到以下错误。

sock.sendto(message, (UDP_IP, UDP_PORT))
TypeError: a bytes-like object is required, not 'int'

My question is: How do I convert a c_void_p to a byte array that sock.sendto can accept.? 我的问题是:如何将c_void_p转换为sock.sendto可以接受的字节数组。

I have tried to reduce my code as much as possible and still make it understandable. 我尽可能地减少了我的代码,但仍然可以理解。

This is my C code 这是我的C代码

// C DLL code 
// 

#define DllExport extern "C" __declspec( dllexport )

typedef uint16_t(*FPCallbackSendMessage)(const uint8_t * message, const uint32_t length);
FPCallbackSendMessage g_CallbackSendMessage;

DllExport bool RegisterCallbackSendMessage(uint16_t(*p_CallbackSendMessage)(const uint8_t * message, const uint32_t length)) {
    g_CallbackSendMessage = p_CallbackSendMessage ; 
    return true;
}

void SendWhoIs(unsigned int dd) {
    printf("dd=%d", dd); 
    char buffer[500];
    g_CallbackSendMessage( buffer, 500 ); 
}

And this is my python code 这是我的python代码

# Python code 
# =================
print("Start") 

customDLL = cdll.LoadLibrary ("customeDLL.dll")

def SendMessage( message, length ):
    print("SendMessage...") 
    UDP_IP = "192.168.1.1"
    UDP_PORT = 47808
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(message, (UDP_IP, UDP_PORT))
    return True 

print("Registering Callback SendMessage...") 
SendMessageFUNC = CFUNCTYPE(c_bool, c_void_p, c_uint)
SendMessage_func = SendMessageFUNC( SendMessage )

RegisterCallbackSendMessage = customDLL.RegisterCallbackSendMessage
RegisterCallbackSendMessage.argtypes = [ SendMessageFUNC ]
RegisterCallbackSendMessage( SendMessage_func ) 

print("Do message...") 
SendWhoIs = BACnetStackDLL.SendWhoIs
SendWhoIs.argtypes = [c_uint]

SendWhoIs( 47 )

print("End") 

I figured it out. 我想到了。

in the python SendMessage function I figured out a way to convert the c_void_p to a byte array. 在python SendMessage函数中,我想出了一种将c_void_p转换为字节数组的方法。

# convert the pointer to a buffer. 
buffer = c_char * length 
messageToSend = buffer.from_address(message)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM