我正在编写一个Python客户端来连接用C编写的服务器,该服务器以二进制结构发送状态。我用SWIG封装了C结构,但是我需要处理从套接字返回的数据作为C结构。特别是,我想将传递给dataReceived()的数据转换为iwrf_ui_task_operations
结构。
我是否需要编写(和SWIG)传递'data'的辅助函数,并返回iwrf_ui_task_operations
结构?
这是一个简单的测试程序:
from twisted.internet import reactor, protocol
import syscon_interface
class SysconClient(protocol.Protocol):
"""Once connected, receive messages from syscon."""
def connectionMade(self):
print "connectionMade"
def dataReceived(self, data):
"As soon as any data is received, write it out."
# this constructor does not accept 'data' as an argument :-(
to = syscon_interface.iwrf_ui_task_operations_t()
print "Server said:", data
def connectionLost(self, reason):
print "connection lost"
class SysconClientFactory(protocol.ClientFactory):
protocol = SysconClient
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
reactor.stop()
# this connects the protocol to a server running on port 2515
def main():
f = SysconClientFactory()
reactor.connectTCP("localhost", 2515, f)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
答案 0 :(得分:4)
你不想这样做。传递给dataReceived
的数据是TCP段,而不是协议消息。因此,您可能会收到一些结构,或全部结构,或多个结构,或从中间开始的数据。
请参阅this Twisted FAQ。
你根本不想这样做。不同的C编译器可以完全有效地为这个结构生成不同的布局,并且您的平台的字节序将会涉及,而且通常只是一个糟糕的场景。
如果您打算这样做(并且基于您的问题的框架,我认为您必须这样做),首先您需要确保您的确切工具链版本(C编译器版本,SWIG版本,Python版本) ,Python构建选项等等都是完全同步的。然后你需要编写一个框架协议,like those in twisted.protocols.basic
,它处理基于sizeof(iwrf_ui_task_operations_t)
的固定宽度记录,然后一旦你拆分它,一个包装函数需要{{1}和char* data
并构造你的结构将是合乎逻辑的下一步。
最后,不要使用SWIG,请使用CFFI。编写绑定更加容易,对其他运行时更容易移植(例如,PyPy实际上可以将您的调用JIT调到C中),并且实质上更安全(更少的段错误机会)。