我有一个导出此功能的C dll:
DECLDIR int runTest (char *historyPath, unsigned int candleNumber, void (*testUpdate)(double percentageOfTestCompleted), void (*testFinished)(void), char **error);
我正在尝试以这种方式在我的python脚本中使用该函数:
historyFilePath_c = c_char_p(historyFilePath)
candleNumber_c = c_int(1000)
error_c = c_char_p(300);
TEST_UPDATE = CFUNCTYPE(c_int, POINTER(c_double))
testUpdate_c = TEST_UPDATE(testUpdate)
TEST_FINISHED = CFUNCTYPE(c_int)
testFinished_c = TEST_FINISHED(testFinished)
astdll.runTest (historyFilePath_c, candleNumber_c, testUpdate_c, testFinished_c, byref(error_c))
def testUpdate(percentageOfTestCompleted):
print 'Test running ' , percentageOfTestCompleted[0]
return True
def testFinished():
print 'Test finished!!'
return True
我收到此错误(多次因为回调函数运行了很多次。我只会留下最后一个错误。所有这些都是一样的)
Test running
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 314, in 'calling callback function'
File "ast.py", line 67, in testUpdate
print 'Test running ' , percentageOfTestCompleted[0]
ValueError: NULL pointer access
Test finished!!
答案 0 :(得分:2)
testUpdate
回调按值double
取值,而不是指针,两个回调都返回void
,即None
。
candleNumber_c
是不必要的,特别是如果您声明argtypes
。这同样适用于historyFilePath_c
。 Python字符串已经包含指向以null结尾的字符串的指针,这是c_char_p
构造函数使用的。
为什么要将error_c
初始化为地址300?
以下是一个应该有用的示例:
<强> tmp.py:强>
from ctypes import *
lib = CDLL('./tmp.so')
c_test_update_t = CFUNCTYPE(None, c_double)
c_test_finished_t = CFUNCTYPE(None)
run_test = lib.runTest
run_test.argtypes = [
c_char_p, c_uint, c_test_update_t, c_test_finished_t,
POINTER(c_char_p)]
def test_update(percent_completed):
print 'percent completed:', percent_completed
test_update_c = c_test_update_t(test_update)
def test_finished():
print 'test finished'
test_finished_c = c_test_finished_t(test_finished)
error = c_char_p()
result = run_test(
'path/to/history', 1000, test_update_c, test_finished_c,
byref(error))
print result
print error.value
<强> tmp.c:强>
#include <stdio.h>
char error_string[] = "error string";
int runTest(
char *historyPath,
unsigned int candleNumber,
void (*testUpdate)(double percentageOfTestCompleted),
void (*testFinished)(void),
char **error)
{
printf("historyPath: %s\n", historyPath);
printf("candleNumber: %d\n", candleNumber);
testUpdate(0.0);
testFinished();
*error = error_string;
return 0;
}
(只是一个简单的测试库,在Linux上用gcc编译)
<强>输出:强>
historyPath: path/to/history
candleNumber: 1000
percent completed: 0.0
test finished
0
error string