2016-04-03 26 views
1

我試圖使用ctypes的從蟒蛇一個dll互動,閱讀文檔的C++方法簽名下面的ctypes的從Python中調用C++方法:使用不工作

my_c_pp_function(user *param1[],const int_8 param2,const int_8 values3[],const int_8 length_param1) 

本質上的C++函數需要用戶列表,整數,值列表和用戶數量,也是一個整數

注意:用戶是包含名稱,年齡和id的結構 。喜歡的東西:

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的功能我得到一個錯誤,基本上,如果函數成功返回值應該是0,任何非零數字表示某種問題。

我不斷收到一個大的非零數字作爲返回值。 我可能會做錯什麼?是我創建用戶數組的方式,而數組的值錯誤?

我不知道如何填充/利用C用戶結構++在我的Python代碼,使我的名單不只是一個字符串列表,但我使用Python2.7用戶

列表

在Windows上

Regards

+0

如果第一個參數是真的* *一個'STD :: STRI因爲'char *'是**而不是'std :: string' – Petesh

+0

你不能在函數的公共接口中使用'std :: string'因爲它是一個C++類型)。 'ctypes'只提供對C兼容數據類型的支持。 – foo

+0

要調用它,你必須知道如何構建或以其他方式獲得'users',但是你沒有向我們展示任何有關這種類型的東西。 – Flexo

回答

1

假設您不能更改庫函數的簽名。

我建議你爲你的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; 
} 
+0

感謝您的幫助。對此,我真的非常感激。 – user595985