0

我有一个导出此函数的 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!!
4

1 回答 1

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
于 2013-04-19T17:52:11.893 回答