使用 ctypes 调用指向定义为静态的函数的函数指针

using ctypes to call a function pointer that points to a function that is defined static

我正在使用 Python 3.6.0 和 ctypes 来访问从 .dll 导出的函数。我想通过使用 paramflags 参数实例化函数原型来访问这些函数。 .dll 中的一个函数被定义为静态的,因此它不会被导出。然而,.dll 还包含一个指向该函数并被导出的函数指针。

这是 .dll 的简化版本

typedef void ( *function ) ( int *output, int input );

__declspec( dllexport ) void two( int *output, int input );

__declspec( dllexport ) extern const function four;

void two( int *output, int input ) {
    *output =  2 * input;
}

static void three( int *output, int input ) {
    *output =  3 * input;
}

const function four = three;

这是我的 Python 代码

import ctypes

dll = ctypes.cdll.test

# calling two( ) as an attribute of dll
two = dll.two
two.argtypes = [ ctypes.POINTER( ctypes.c_int ), ctypes.c_int ]
two.restype = None
output = ctypes.c_int( )
# output = c_long(2)
two( ctypes.byref( output ), 1 )
print( 'output =', output )

# calling two( ) by instantiating a function prototype with paramflags
function = ctypes.CFUNCTYPE( None, ctypes.POINTER( ctypes.c_int ), ctypes.c_int )
paramflags = ( ( 2, 'output' ), ( 1, 'input' ) )
two = function( ( 'two', dll ), paramflags )
# output = 2
output = two( 1 )
print( 'output =', output )

# I can call four( ) using in_dll( )
four = function.in_dll( dll, 'four' )
output = ctypes.c_int( )
# output = c_long(3)
four( ctypes.byref( output ), 1 )
print( 'output =', output )

# but not as an attribute of dll
four = dll.four
four.argtypes = [ ctypes.POINTER( ctypes.c_int ), ctypes.c_int ]
four.restype = None
output = ctypes.c_int( )
# this results in a "OSError: exception: access violation writing 0x6C0C3064"
four( ctypes.byref( output ), 1 )
print( 'output =', output )

# nor by instantiating a function prototype
paramflags = ( ( 2, 'output' ), ( 1, 'input' ) )
four = function( ( 'four', dll ), paramflags )
# this results in a "OSError: exception: access violation writing 0x6C0C3064"
output = four( 1 )
print( 'output =', output )

我可以访问 two( ) 作为 dll 的一个属性,并通过实例化一个函数原型。但是,当我尝试使用 four( ) 执行此操作时,我得到 "OSError: exception: access violation writing 0x6C0C3064"。经过大量试验后,我发现我可以使用 in_dll( ) 访问 four( ),但是我无法应用 paramflags 功能。

有什么方法可以访问 four( ) 并使用 paramflags 吗?

注意:我不想更改 dll(它不是我的项目的一部分)并且正在尝试在 Python 方面解决它。

"I am using Python 3.6.0 and ctypes to access functions exported from a .dll."我认为问题如下。

这个

typedef void ( *function ) ( int *output, int input );
__declspec( dllexport ) extern const function four;

实际上并没有从 dll 中导出一个函数,而只是一个指向 typedef 函数的指针,它被声明为 extern。最后,Symbol Exporter 没有任何实际用处。 例如,如果您在构建后在生成的库中查找,您会发现对两个的清晰引用,但对四个的引用却一团糟。

如果你声明四个函数regulary

__declspec( dllexport ) const void four( int *output, int input );

然后定义函数regulary

const void four( int *output, int input ) {
    *output =  3 * input;
}

那么您应该能够访问 four() 并使用 paramflags。

我玩了一会儿,但由于使用 paramflags 实例化函数的方法需要语法中的导出函数名称和 DLL,因此它不考虑导出的全局函数 指针.

当然,您可以通过定义要分配的包装器和 return 输出参数来获得相同的行为,只需做一些工作:

_four = function.in_dll( dll, 'four' )
def four(input):
    output = ctypes.c_int()
    _four(output,input)
    return output.value
output = four(5)
print('output =',output)