我知道在dll / so中调用cpp函数是不合适的,例如。 [AVFormatIDKey: kAudioFormatAppleLossless,AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue,
AVEncoderBitRateKey: 320000,
AVNumberOfChannelsKey: 2,
AVSampleRateKey: 44100.2] as [String: Any]
之所以int foo(int&)
,是因为ctpyes
中没有等效的引用变量概念。但是我想展示一个这样做的演示,我对python的行为(版本3.7)感到非常困惑。
基本上,我有一个来自其他人的dll,我相信它是由vs c ++构建的,并使用c
导出。 dll中有一些接口采用extern "C"
的形式。当我使用python时,我需要一个int foo(int&)
层来包装它。例如,
ctypes
转换为(_foo由int foo(int&)
加载)
ctypes
然后我像python一样调用_foo.argtypes = [POINTER(c_int)]
_foo.restype = c_int
foo
和它的工作原理。 我使用以下代码在linux演示中进行了进一步的测试,
demo.cpp
i = c_int(1)
_foo(i)
构建
#include <stdio.h>
extern "C" int foo(int&);
int foo(int& i)
{
printf("foo is called.\n");
printf("Got i: %d\n", i);
i += 10;
printf("Set i: %d\n", i);
return 0;
}
因此,构建了g++ -Wall -fPIC -c demo.cpp
g++ -shared -Wl,-soname,libdemo.so.1 -o libdemo.so demo.o
。
demo.py
libdemo.so
如果我运行demo.py
#!/usr/bin/env python3
from ctypes import CDLL, c_int,POINTER
l = CDLL("libdemo.so")
_foo = l.foo
_foo.argtypes = [POINTER(c_int)]
_foo.restype = c_int
def foo(i):
print("Input: i",i)
_i = c_int(i)
r = _foo(_i)
i = _i.value
print("Output: i", i)
foo(1)
它会很好地工作,并给我正确的答案,即
LD_LIBRARY_PATH=. ./demo.py
然后,如果我通过Input: i 1
foo is called.
Got i: 1
Set i: 11
Output: i 11
通过了i
,则将byref
更改为
demo.py
它仍然按原样工作,并输出相同的结果。
那么,幕后发生了什么?为什么上述两个版本#!/usr/bin/env python3
from ctypes import CDLL, c_int,POINTER,byref
l = CDLL("libdemo.so")
_demo = l.demo
_demo.argtypes = [PONTER(c_int)]
_demo.restype = c_int
def demo(i):
print("Input: i",i)
_i = c_int(i)
r = _demo(byref(_i)) # calling by byref
i = _i.value
print("Output: i", i)
demo(1)
具有相同的输出?我可以依靠这种功能来使用demo.py
来调用cpp函数,该函数可以通过引用获得参数吗?