使用 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)
我正在使用 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)