Linux 如何在Python2.7中使用ctypes返回指针字符串

Linux 如何在Python2.7中使用ctypes返回指针字符串,linux,python-2.7,ctypes,Linux,Python 2.7,Ctypes,我正在实施新的财政手段。它使用OPOS/UPOS库进行通信。我对ctypes非常陌生,对C完全没有经验。然而,我已经设法使它工作,大部分 但是我在从generalist方法DirectIO返回字符串时遇到问题。文档说明:“此命令应在endFiscalReceive()之后立即使用,以检索最新收据的唯一ID” “参数: –数据[in] 忽略。 –Obj[输入/输出] 要读取的值。” 并在下面添加了.NET示例: int iData = 0; string strReferenceID = "";

我正在实施新的财政手段。它使用OPOS/UPOS库进行通信。我对
ctypes
非常陌生,对C完全没有经验。然而,我已经设法使它工作,大部分

但是我在从generalist方法
DirectIO
返回字符串时遇到问题。文档说明:“此命令应在endFiscalReceive()之后立即使用,以检索最新收据的唯一ID”

“参数: –数据[in] 忽略。 –Obj[输入/输出] 要读取的值。”

并在下面添加了.NET示例:

int iData = 0;
string strReferenceID = "";
fiscalPrinter.EndFiscalReceipt();
fiscalPrinter.DirectIO(CMD_EKASA_RECEIPT_ID, ref iData, ref strReferenceID);
// strReferenceID will contain latest receipt ID, e.g. "O−7DBCDA8A56EE426DBCDA8A56EE426D1A"
第一个参数(CMD_EKASA_receive_ID)是执行的命令,这就是上面没有列出的原因

然而,python不是.NET,我从未使用过.NET

我一直遵循ctypes doku()中的说明,定义此方法参数并在init中返回:

self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
self.libc.DirectIO.restype = ctypes.c_char_p
然后尝试了不同的方法来检索回复字符串,但在我的情况下,这两种方法都不起作用:

s = ""
c_s = ctypes.c_char_p(s)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, c_s)

p = ctypes.create_string_buffer(40)
poin = ctypes.pointer(p)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, poin)

p = ctypes.create_string_buffer(40)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, p)

s = ctypes.create_string_buffer('\000' * 32)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, s)
我创建的string对象在校准Cmethod后总是空的,也就是说,
,就像我创建的一样

然而,还有一件事,对我来说没有意义。我的同事向我展示了如何在头文件中查看方法参数和返回。对于这一个,有这样一个:

int DirectIO(int iCommand, int* piData, const char* pccString);
也就是说,它返回整数?如果我没弄错的话

所以,我想的是,我必须向这个方法传递一些指向一个字符串的指针,这个字符串是用python创建的,C将把它改成我应该读的内容。因此,我认为我思考解决方案的方式是正确的

我也尝试过这种方法,但这对我也不起作用


我开始感到绝望。不确定我是否正确理解了问题,是否正在寻找解决方案。

标签中有
linux
,但OPOS在linux上不起作用

或者,您是否在Wine等仿真环境中工作

在任何情况下,如果你没有合适的环境,你可能会因为一点小事而陷入麻烦

首先,在Windows 32位环境中工作,创建在那里工作的东西,然后将其移植到另一个环境

由于OPOS使用OLE/COM技术,因此要使用的第一个包是
win32com
comtypes


UnifiedPOS是一个概念性规范,没有实际的软件组件

实际运行的软件有三种:OPOS、JavaPOS和POS for.NET。
OPOS和POS for.NET只能在Windows 32位环境中工作

只有JavaPOS可以在Linux环境中工作,并且通常只能从Java获得

如果您想用Python制作一些东西,您需要创建一个从Python调用Java的包装器(或胶水)库


如果C接口UnifiedPOS(OPOS)在Linux上运行时未使用Windows emulator或Java包装器,则它可能是打印机供应商参考UnifiedPOS创建的原始库/组件

在这种情况下,我认为详细的规范只能从创建它的供应商那里听到


为了解释,DirectIO方法和DirectIOEvent被定义为供应商可以自由定义和使用的方法/事件

因此,UnifiedPOS文档中只定义了方法/事件名称和参数

有必要询问提供DirectIO方法/DirectIOEvent的供应商特定供应商的服务对象具有什么功能,由供应商确定参数的含义

OPOS规范从中间被UnifiedPO吸收,但在此之前,它作为一个单一规范存在

名字的其余部分在这里

这是您的库的方法返回值为整数的根

顺便说一下,这是目前最新的UnifiedPOS规范。

我已经解决了我的问题。整个事情是,在分配内存方面。我读过的网络上的每个例子都创建了空字符串,比如
s=”“
。但是,这是不对的

当分配空字符串时,C库没有内存来写入结果

这几乎是正确的做法,

self.libc = ctypes.cdll.LoadLibrary(LIB_PATH)
self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
result_s = ctypes.c_char_p("")
log.info('S address: %s | S.value: "%s"' % (result_s, result_s.value))
self.libc.DirectIO(CMD_EKASA_RECEIPT_ID, 0, result_s)
log.info('S address: %s | S.value: "%s"' % (result_s, result_s.value))
返回:

S address: c_char_p(140192115373700) | S.value: ""
S address: c_char_p(140192115373700) | S.value: ""
只需稍作修改:

self.libc = ctypes.cdll.LoadLibrary(LIB_PATH)
self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
result_s = ctypes.c_char_p(" " * 10)
log.info('S address: %s | S.value: %s' % (result_s, result_s.value))
self.libc.DirectIO(CMD_EKASA_RECEIPT_ID, 0, result_s)
log.info('S address: %s | S.value: %s' % (result_s, result_s.value))
现在,调用
self.libc.DirectIO
后打印
result\u s
确实会返回与调用前不同的字符串

S address: c_char_p(140532072777764) | S.value: "          "
S address: c_char_p(140532072777764) | S.value: "0-C12A22F5"

它是为Linux环境创建的包。他们称之为UnifiedPOS(),这基本上是OPOS的派生。但是UPOS标签在这里不起作用。基本上都是相同的库方法。我没有问题连接到设备,我甚至可以打印财政票据没有问题。当我必须从设备中获取一些值时,我的麻烦就开始了。我的问题更多的是关于
ctypes
python
而不是库。如果OPOS标记有误导性,可以删除它。DirectIO的C原型是什么?抱歉,但我不理解您的问题。您可以使用
ctypes。创建字符串缓冲区(10)
而不是
ctypes.C\u字符p(''*10)