2016-04-03 19 views
1

arbeiten Ich versuche, mit einer DLL-Datei von Python zu interagieren ctypes Sie in der Dokumentation lesen die C++ Methodensignatur der folgenden ist:ctypes mit nicht

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

Wesentlichen die C++ Funktion a erfordert Liste der Benutzer, eine ganze Zahl, eine Liste von Werten und die Anzahl der Benutzer, auch eine ganze Zahl

Hinweis: Der Benutzer ist eine Struktur enthält Name, Alter und ID. Etwas wie:

typedef struct 
{ 
char name[255]; 
int_16 age; 
int_32 uid; 
}user; 

Wenn ich versuche, diese Funktion von Python-Code aufrufe ctypes mit mir tun:

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) 

Nun jedes Mal, ich rufe die Python-Funktion, die ich einen Fehler im Grunde, wenn die Funktion die Rückkehr gelingt Wert sollte 0 sein, jede Zahl ungleich Null zeigt eine Art von Problem an.

Ich bekomme immer eine große von Null verschiedene Zahl als Rückgabewert. Was könnte ich möglicherweise falsch machen? ist die Art, wie ich das Array von Benutzern erstellen, und das Array von Werten falsch?

Ich bin nicht sicher, wie zum Auffüllen/Nutzung der C++ Benutzerstruktur in meinem Python-Code, so dass meine Liste nicht nur eine Liste von Strings, sondern eine Liste der Benutzer

Ich bin mit python2.7 auf

Windows-

Grüße

+0

Wenn der erste Parameter ist * wirklich * a 'std :: str ng * 'müssen Sie einen Weg finden, es zu füllen, da' char * '** nicht ** ein' std :: string' ist – Petesh

+0

Sie können 'std :: string' nicht in der öffentlichen Schnittstelle der Funktion verwenden (da es ein C++ Typ ist). 'ctypes' bietet nur Unterstützung für C-kompatible Datentypen. – foo

+0

Um es zu nennen, müssen Sie wissen, wie man 'Benutzer' konstruiert oder anderweitig erhält, aber Sie haben uns nichts über diesen Typ gezeigt. – Flexo

Antwort

1

Unter der Annahme, dass Sie nicht die Unterschrift Ihrer Bibliothek Funktion ändern können.

Ich würde Ihnen empfehlen, einen einfachen Adapter für Ihre c++ Funktion zu erstellen, die nur als Schnittstelle zu Ihrer eigentlichen Funktion fungiert. Diese Funktion würde nur alle Werte übernehmen, die Sie benötigen, und sie dann in die benötigten Typen konvertieren.

Hier ist ein Arbeitsbeispiel (getestet mit Python27). Beachten Sie, dass ich einen zusätzlichen Parameter für die Anzahl der Elemente im Array int hinzugefügt habe.

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

Danke für Ihre Hilfe. Ich schätze es sehr. – user595985