使用 ctypes 从 Python 调用 C++ 方法不起作用
Calling C++ Method from Python using ctypes not working
我正在尝试使用 ctypes 与来自 python 的 dll 进行交互,阅读 C++ 方法签名的文档如下:
my_c_pp_function(user *param1[],const int_8 param2,const int_8 values3[],const int_8 length_param1)
本质上,c++ 函数需要一个用户列表、一个整数、一个值列表和用户数,也是一个整数
注:users是一个结构体
包含姓名、年龄和身份证。类似于:
typedef struct
{
char name[255];
int_16 age;
int_32 uid;
}user;
当我尝试使用 ctypes 从 python 代码调用此函数时,我这样做:
def call_my_c_pp_function(list_of_users,int_param2,list_of_values,int_lenght_of_list):
myparam1=(ctypes.c_char_p * len(list_of_users))(*list_of_users)
myparam2=ctypes.c_int8(int_param2)
myparam3=(ctypes.c_int8 * len(list_of_values))(*list_of_values)
myparam4=ctypes.c_int8(int_lenght_of_list)
self.dll_object.my_c_pp_function.argtypes(ctypes.POINTER(ctypes.c_char_p),ctypes.c_int8,ctypes.POINTER(ctypes.c_int8),ctypes.c_int8)
ret_value=self.dll_object.my_c_pp_function(myparam1,myparam2,myparam3,myparam4)
现在每次我调用 python 函数时,如果函数成功 return 值应该为 0,我基本上都会得到一个错误,任何非零数字都表示存在某种问题。
我不断得到一个很大的非零数字作为 return 值。
我可能做错了什么?我创建用户数组和值数组的方式是错误的吗?
我不确定如何 populate/make 在我的 python 代码中使用 c++ 用户结构,以便我的列表不仅仅是一个字符串列表,而是一个用户列表
我在 Windows
上使用 Python2.7
此致
假设您无法更改库函数的签名。
我建议您为 c++
函数创建一个简单的适配器,它只是作为您实际函数的接口。
此函数只会获取您需要的所有值,然后将它们转换为您需要的类型。
这是一个工作示例(使用 python27 测试)。请注意,我为 int
数组中的元素数量添加了一个附加参数。
py_caller.py
import ctypes
import os
class user(ctypes.Structure):
_fields_ = [("name", ctypes.c_char_p),
("age", ctypes.c_int),
("uid", ctypes.c_int)]
def create_users(count):
users = (user * count)()
for i in range(count):
users[i].name = ctypes.c_char_p("user" + str(i))
users[i].age = i
users[i].uid = i * i
return users
def create_values(count):
values = (ctypes.c_int * count)()
for i in range(count):
values[i] = i ** 2
return values
def main():
os.environ['PATH'] += ";" + os.path.dirname(os.path.abspath(__file__))
dll = ctypes.cdll.LoadLibrary('cppdll')
count = 4
users = create_users(count)
n_users = ctypes.c_int(count)
values = create_values(count)
n_values = ctypes.c_int(count)
some_int = ctypes.c_int(42)
res = dll.func(users, n_users, some_int, values, n_values)
print (res)
if __name__ == "__main__":
main()
export.h
#pragma once
typedef struct t_user
{
char *name;
int age;
int uid;
};
extern "C" __declspec(dllexport) int func(t_user *users, int n_users, int val, int *values, int n_values);
export.cpp
#include "export.h"
#include <iostream>
int func(t_user *users, int n_users, int val, int *values, int n_values)
{
std::cout << "users:\n";
for (auto i = 0; i < n_users; ++i)
{
std::cout << users[i].name
<< ": " << users[i].age
<< " - " << users[i].uid << "\n";
}
std::cout << "values:\n";
for (auto i = 0; i < n_values; ++i)
std::cout << values[i] << "\n";
std::cout << "some int: " << val << "\n";
// do something else with the values
// such as calling your actual library function
return 1;
}
我正在尝试使用 ctypes 与来自 python 的 dll 进行交互,阅读 C++ 方法签名的文档如下:
my_c_pp_function(user *param1[],const int_8 param2,const int_8 values3[],const int_8 length_param1)
本质上,c++ 函数需要一个用户列表、一个整数、一个值列表和用户数,也是一个整数
注:users是一个结构体 包含姓名、年龄和身份证。类似于:
typedef struct
{
char name[255];
int_16 age;
int_32 uid;
}user;
当我尝试使用 ctypes 从 python 代码调用此函数时,我这样做:
def call_my_c_pp_function(list_of_users,int_param2,list_of_values,int_lenght_of_list):
myparam1=(ctypes.c_char_p * len(list_of_users))(*list_of_users)
myparam2=ctypes.c_int8(int_param2)
myparam3=(ctypes.c_int8 * len(list_of_values))(*list_of_values)
myparam4=ctypes.c_int8(int_lenght_of_list)
self.dll_object.my_c_pp_function.argtypes(ctypes.POINTER(ctypes.c_char_p),ctypes.c_int8,ctypes.POINTER(ctypes.c_int8),ctypes.c_int8)
ret_value=self.dll_object.my_c_pp_function(myparam1,myparam2,myparam3,myparam4)
现在每次我调用 python 函数时,如果函数成功 return 值应该为 0,我基本上都会得到一个错误,任何非零数字都表示存在某种问题。
我不断得到一个很大的非零数字作为 return 值。 我可能做错了什么?我创建用户数组和值数组的方式是错误的吗?
我不确定如何 populate/make 在我的 python 代码中使用 c++ 用户结构,以便我的列表不仅仅是一个字符串列表,而是一个用户列表
我在 Windows
上使用 Python2.7此致
假设您无法更改库函数的签名。
我建议您为 c++
函数创建一个简单的适配器,它只是作为您实际函数的接口。
此函数只会获取您需要的所有值,然后将它们转换为您需要的类型。
这是一个工作示例(使用 python27 测试)。请注意,我为 int
数组中的元素数量添加了一个附加参数。
py_caller.py
import ctypes
import os
class user(ctypes.Structure):
_fields_ = [("name", ctypes.c_char_p),
("age", ctypes.c_int),
("uid", ctypes.c_int)]
def create_users(count):
users = (user * count)()
for i in range(count):
users[i].name = ctypes.c_char_p("user" + str(i))
users[i].age = i
users[i].uid = i * i
return users
def create_values(count):
values = (ctypes.c_int * count)()
for i in range(count):
values[i] = i ** 2
return values
def main():
os.environ['PATH'] += ";" + os.path.dirname(os.path.abspath(__file__))
dll = ctypes.cdll.LoadLibrary('cppdll')
count = 4
users = create_users(count)
n_users = ctypes.c_int(count)
values = create_values(count)
n_values = ctypes.c_int(count)
some_int = ctypes.c_int(42)
res = dll.func(users, n_users, some_int, values, n_values)
print (res)
if __name__ == "__main__":
main()
export.h
#pragma once
typedef struct t_user
{
char *name;
int age;
int uid;
};
extern "C" __declspec(dllexport) int func(t_user *users, int n_users, int val, int *values, int n_values);
export.cpp
#include "export.h"
#include <iostream>
int func(t_user *users, int n_users, int val, int *values, int n_values)
{
std::cout << "users:\n";
for (auto i = 0; i < n_users; ++i)
{
std::cout << users[i].name
<< ": " << users[i].age
<< " - " << users[i].uid << "\n";
}
std::cout << "values:\n";
for (auto i = 0; i < n_values; ++i)
std::cout << values[i] << "\n";
std::cout << "some int: " << val << "\n";
// do something else with the values
// such as calling your actual library function
return 1;
}