使用ctypes返回值

时间:2015-11-20 23:16:16

标签: python c++ python-2.7 ctypes

我正在研究从Python调用C ++代码。我刚刚了解了ctypes,并在网上看到了一些例子。我试图调用一个类似于以下内容的C ++函数:

get_data(re * data_record, char * string)

对c ++一无所知,我会问一些基础知识。 应该如何使用ctypes从python调用这样的函数。 我已经决定退后一步,因为我觉得我在这里错过了一些基本原则。

事实上,对于任何采用string类型的参数并返回整数的C ++函数,请参阅一些示例

struct db_obj {
    char db_name[50],
    int_32 db_guid,
    char db_path[100];
};

get_database_running_status(db *db_obj,int_8 db_id,int_8 *retvalue);

get_database_running_status_string(db *db_obj,int_8 db_id,char *retvalue);

此函数将返回一个状态值(retvalue),我可以解码它以了解数据库的状态,例如10 =正常运行,11 = stropped,12 =暂停,404 =故障等。

虽然get_database_running_status_string将返回字符串而不仅仅是数字

我该怎么称呼这些?不知道那个*符号是什么,尽管我希望它有所帮助。

也许一旦我理解了如何从python正确调用C ++函数,那么我的问题可能会自行解决。

1 个答案:

答案 0 :(得分:0)

发布工作C ++代码的实际示例会有所帮助,但我只是创建类似于演示的东西。

这是一个简短的C ++ DLL源代码。由于ctypes包含C函数而不是C ++,因此函数被声明为extern "C"才能正常工作。我在Windows上执行此操作,因此__declspec(dllexport)用于将函数标记为从DLL导出:

#include <stdio.h>

struct record {
    int x,y;
};

typedef int int_32;
typedef char int_8;

struct db_obj {
    char db_name[50];
    int_32 db_guid;
    char db_path[100];
};

extern "C" {
    __declspec(dllexport) void get_data_int(record* pRec, int* pResult) {
        *pResult = pRec->x + pRec->y;
    };
    __declspec(dllexport) void get_data_string(record* pRec, char* pResult, size_t size) {
        sprintf_s(pResult,size,"%d + %d = %d\n", pRec->x, pRec->y, pRec->x + pRec->y);
    }
    __declspec(dllexport) void get_database_running_status(db_obj* db, int_8 db_id, int_8 *retvalue) {
        printf("db_name = %s\ndb_guid = %d\ndb_path = %s\ndb_id = %d\n", db->db_name, db->db_guid, db->db_path, db_id);
        *retvalue = 42;
    }
}

这是ctypes包装器:

#!python2
import ctypes as c

class Record(c.Structure):
    _fields_ = [('x',c.c_int),('y',c.c_int)]

class db_obj(c.Structure):
    _fields_ = [('db_name',c.c_char * 50),
                ('db_guid',c.c_int),
                ('db_path',c.c_char * 100)]

dll = c.CDLL('x')

get_data_int = dll.get_data_int
get_data_int.argtypes = [c.POINTER(Record), c.POINTER(c.c_int)]
get_data_int.restype = None

get_data_string = dll.get_data_string
get_data_string.argtypes = [c.POINTER(Record), c.POINTER(c.c_char), c.c_size_t]
get_data_string.restype = None

get_database_running_status = dll.get_database_running_status
get_database_running_status.argtypes = [c.POINTER(db_obj), c.c_int8, c.POINTER(c.c_int8)]
get_database_running_status.restype = None

result = c.c_int()
rec = Record(5,7)
get_data_int(c.byref(rec),c.byref(result))
print(result.value)

result = c.create_string_buffer(50)
rec = Record(5,7)
get_data_string(c.byref(rec),result,c.sizeof(result))
print(result.value)

result = c.c_int8()
db = db_obj('database name',1234,'database path')
get_database_running_status(c.byref(db),7,c.byref(result))
print(result.value)

输出:

12
5 + 7 = 12

db_name = database name
db_guid = 1234
db_path = database path
db_id = 7
42

有关详细信息,请参阅ctypes文档。