C DLL(unitybridge.DLL)对Python函数的异步回调

C DLL(unitybridge.DLL)对Python函数的异步回调,python,c,unity3d,dll,ctypes,Python,C,Unity3d,Dll,Ctypes,我正在基于Golang()中的代码用Python重新设计DJI Robomaster S1应用程序。在这段代码中,他们使用了一个unitybridge.dll来完成与机器人的大部分通信。与此dll的通信主要通过(异步)回调进行。我使用ctypes访问C中的代码。 我使用了一个C库“libffcall”,它返回一个指向回调的指针(也用于Go)。由于代码非常复杂,我将在这里举一个小例子,它应该可以工作,但不能。通常,这应该创建、初始化网桥并启动连接(通过发送特定事件)。这些似乎都奏效了。设置回调时,

我正在基于Golang()中的代码用Python重新设计DJI Robomaster S1应用程序。在这段代码中,他们使用了一个unitybridge.dll来完成与机器人的大部分通信。与此dll的通信主要通过(异步)回调进行。我使用ctypes访问C中的代码。
我使用了一个C库“libffcall”,它返回一个指向回调的指针(也用于Go)。由于代码非常复杂,我将在这里举一个小例子,它应该可以工作,但不能。通常,这应该创建、初始化网桥并启动连接(通过发送特定事件)。这些似乎都奏效了。设置回调时,当网桥中发生特定事件(我选择,因为它每隔几秒钟发生一次)时,不会发生任何事情\

alloc\u helper.c:使用libffcall进行回调。为了使事情尽可能简单,回调只打印一些内容:

#include <stdio.h>
#include "alloc_helper.h"
#include "event_callback_windows.h"
#include <stdlib.h>

callback_t alloc_callback_python(void* data) {
   
    return alloc_callback(&event_callback, data);
}
example.py:参数中的值与Go中的值相同

from ctypes import *
import time

# load the C-code
dll = CDLL("./unitybridge.dll")
alloc_helper = CDLL("./alloc_helper.so")

# create bridge args: str name, bool debuggable
dll.CreateUnityBridge(c_char_p(b"Robomaster", c_int(1))

# init bridge (returns True if successfull)
b = dll.UnityBridgeInitialize()
print("BOOL after init: {}".format(b))

# send event that starts connection
# args: event_code, data, sub_type
dll.UnitySendEvent(c_unint64(100 << 32), None, 0)

# set returntype
alloc_helper.alloc_callback_python.restype = POINTER(c_int)

# make callback
cb = alloc_helper.alloc_callback_python(None) # None to make is as simple as possible

# set event callback
# args: event_code (when this events occurs: call cb), callback
dll.UnitySetEventCallback(c_uint(304 << 32), cb)

time.sleep(3) # to give the bridge some time to make callbacks

# uninit and destroy bridge
dll.UnityBridgeUninitialze() # typo is not a mistake -> defined that way in dll
dll.DestroyUnityBridge()
time.sleep(5)

从ctypes导入*
导入时间
#加载C代码
dll=CDLL(“./unitybridge.dll”)
alloc\u helper=CDLL(“./alloc\u helper.so”)
#创建桥参数:str名称,bool可调试
CreateUnityBridge(c_char_p(b“Robomaster”,c_int(1))
#初始化桥(如果成功则返回True)
b=dll.UnityBridgeInitialize()
打印(“初始化后BOOL:{}”。格式(b))
#发送启动连接的事件
#参数:事件代码、数据、子类型

dll.UnitySendEvent(c_unint64(100
ctypes
可以直接包装Python函数并将其传递给C调用,因此这看起来非常复杂。还要确保在函数上正确设置
.argtypes
。这通常是失败的原因,您不必在
ctypes
对象中包装参数,例如
C\u uint64(100FYI,Python中的回调示例:我昨天修复了它。我没有一次破坏桥(没有想法,只是尝试了一些东西)不知何故,下一次运行时它起了作用。但感谢您的回答。另外,正如您所说,如果没有收到错误消息,类型确实需要正确,这可能很困难。
ctypes
可以直接包装Python函数并将其传递给C调用,因此这看起来非常复杂。另外,请确保正确设置
.argtypes
r函数。这通常是失败的原因,您不必将参数包装在
ctypes
对象中,例如
c_uint64(100FYI,Python中的回调示例:我昨天修复了它。我一次运行就没有破坏桥(没有想法,只是尝试了一些东西)不知怎的,下一次运行时它起了作用。但是谢谢你的回答。而且,正如你所说的,类型确实需要正确,如果你没有收到错误消息,这可能会很困难。
from ctypes import *
import time

# load the C-code
dll = CDLL("./unitybridge.dll")
alloc_helper = CDLL("./alloc_helper.so")

# create bridge args: str name, bool debuggable
dll.CreateUnityBridge(c_char_p(b"Robomaster", c_int(1))

# init bridge (returns True if successfull)
b = dll.UnityBridgeInitialize()
print("BOOL after init: {}".format(b))

# send event that starts connection
# args: event_code, data, sub_type
dll.UnitySendEvent(c_unint64(100 << 32), None, 0)

# set returntype
alloc_helper.alloc_callback_python.restype = POINTER(c_int)

# make callback
cb = alloc_helper.alloc_callback_python(None) # None to make is as simple as possible

# set event callback
# args: event_code (when this events occurs: call cb), callback
dll.UnitySetEventCallback(c_uint(304 << 32), cb)

time.sleep(3) # to give the bridge some time to make callbacks

# uninit and destroy bridge
dll.UnityBridgeUninitialze() # typo is not a mistake -> defined that way in dll
dll.DestroyUnityBridge()
time.sleep(5)