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

Question:

I am trying to create a python wrapper for a C DLL. The C DLL uses a callbacks to “send” messages via UDP from the DLL.

What I expected to happen was that python code would load the DLL library and the two functions. Then it would register the call back with the DLL using the RegisterCallbackSendMessage function. The pointer to the callback would be stored in memory in the DLL memory space. Then the python code would call the SendWhoIs DLL function. This function would create a buffer and use the SendMessage function pointer to send the message from the DLL to the python code.

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.

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.?

I have tried to reduce my code as much as possible and still make it understandable.

This is my C code

// 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 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") 
Asked By: Steven Smethurst

||

Answers:

I figured it out.

in the python SendMessage function I figured out a way to convert the c_void_p to a byte array.

# convert the pointer to a buffer. 
buffer = c_char * length 
messageToSend = buffer.from_address(message)
Answered By: Steven Smethurst
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.