2016-09-12 6 views
0

Ich habe dieses Thema recherchiert und die nächste Antwort, die ich gefunden habe, verwendet NuGet Package Manager. Dieses Beispiel finden Sie unter diesem Link. Calling a C# library from pythonAufruf von C# aus Python

In diesem Beispiel gibt der C# -Code eine ganze Zahl zurück. Ich möchte eine Zeichenfolge zurückgeben. Es scheint einfach genug, aber wenn ich eine Zeichenfolge zurückgeben, ist das Ergebnis in Python immer Ganzzahl. Ich habe andere Websites gefunden, die über das Marshalling des Ergebnisdatentyps sprechen, aber ich kann nicht sehen, wie dies funktioniert.

Kann jemand ein Beispiel der "add" -Methode von der obigen Website posten, wo der Rückgabedatentyp eine Zeichenkette ist? Ich möchte keine Beispiele, die IronPython oder Python .Net verwenden. Meine Frage ist über Python 2.7.x und C# nur

Antwort

0

Ich konnte eine Zeichenfolge zurückgeben, indem Sie im Speicher erstellen und übergeben Sie einfach einen Zeiger und die Größe der Zeichenfolge an Python. Ich habe eine example project erstellt, in der ich einige Funktionen getestet habe, um Werte zurückzugeben, bevor ich sie implementiert habe: Im folgenden Beispiel habe ich ein String-Array zurückgegeben. Ich habe einige Änderungen vorgenommen, um das Q anzupassen, damit ich irgendwo einen Fehler gemacht habe.

C#:

[DllExport] 
    static void StringArrayExample(out IntPtr unmanagedArray, out int length)//for ref value you have to use out 
    { 
     var valueList = new[] 
     { 
      "aaa", "bbb", "ccc" 
     }; 

     length = valueList.Length;//return the length of the array 
     IntPtr[] ArrayPtr = new IntPtr[valueList.Length]; 

     for (int i = 0; i < valueList.Length; i++)//create list of string arrays and 
     { 
      byte[] chars = System.Text.Encoding.ASCII.GetBytes(valueList[i] + '\0');//convert string to byte array 
      ArrayPtr[i] = Marshal.AllocHGlobal(chars.Length * Marshal.SizeOf(typeof(char)));//allocate memory to char array, return ptr to location 
      Marshal.Copy(chars, 0, ArrayPtr[i], chars.Length);//copy char array to memory location 
     } 

     //Create memory location to store pointers 
     unmanagedArray = Marshal.AllocHGlobal(valueList.Length * Marshal.SizeOf(typeof(IntPtr))); 
     //copy over all pointer to memory location 
     Marshal.Copy(ArrayPtr, 0, unmanagedArray, ArrayPtr.Length); 

    } 

und die Python-Funktion Diese Funktion aufzurufen: Klasse Arrays ist die Datenstruktur, die ich für ein String-Array verwendet.

Cdll = ctypes.WinDLL("CtypesExamples.dll") 

class Arrays(ctypes.Structure):# 2 string arrays 
    _fields_ = [ ('arr1', ctypes.POINTER(ctypes.c_char_p)), 
       ('size1', ctypes.c_int), 
       ('arr2', ctypes.POINTER(ctypes.c_char_p)), 
       ('size2', ctypes.c_int)] 

def StringArray(self, dllfunc, stringlist): 
    unmanagedArray = ctypes.POINTER(ctypes.c_char_p)()#create ctypes pointer 
    length = ctypes.POINTER(ctypes.c_int)()#create ctypes int 
    #call function with the ctypes pointer and int as ref 
    dllfunc(ctypes.byref(unmanagedArray), ctypes.byref(length)) 

    INTP = ctypes.POINTER(ctypes.c_int)#pointer to int 
    addr = ctypes.addressof(length)#memory address of int 
    arraylength = ctypes.cast(addr, INTP)[0]#cast the pointer to int to a python variable 

    for i in range(0,arraylength): 
     stringlist.append(ctypes.string_at(unmanagedArray[i]).decode(encoding='UTF-8'))#decode convert from bits to string 

    return arraylength 


#send list to c# dll 
stringlist =list() 
arraylength = self.StringArray(Cdll.StringArrayExample, stringlist) 

print(str(arraylength)+" "+str(stringlist[0])+" "+str(stringlist[1])+" "+str(stringlist[2]))