使用ctypes调用具有dll / so中的引用参数的cpp函数的正确方法是什么?

时间:2019-05-13 04:00:14

标签: python ctypes

我知道在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函数,该函数可以通过引用获得参数吗?

0 个答案:

没有答案