Можно ли заставить Python посылать строковый массив переменной длины в C#?
Это обратное / дополнение этого вопроса.
Я использую Unmanaged Exports и ctypes и хочу передать список строк переменной длины из Python в C# и получить строку обратно.
Я пробую четыре варианта C# + Python - ни один не удается. Кто-нибудь может сделать работу?
C#
/* no ref, convert to list */
[DllExport("combineWords1", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string CombineWords1(object obj)
{
var l = (List<string>) obj;
return string.Join(",", l.ToArray());
}
/* no ref, convert to array */
[DllExport("combineWords2", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string CombineWords2(object obj)
{
var l = (string[]) obj;
return string.Join(",", l);
}
/* ref, convert to list */
[DllExport("combineWords3", CallingConvention = CallingConvention.Cdecl)]
public static void CombineWords3(ref object obj)
{
var l = (List<string>)obj;
obj = string.Join(",", l.ToArray());
}
/* ref, convert to array */
[DllExport("combineWords4", CallingConvention = CallingConvention.Cdecl)]
public static void CombineWords4(ref object obj)
{
var l = (string[]) obj;
obj = string.Join(",", l.ToArray());
}
питон
import ctypes
from comtypes.automation import VARIANT
dll = ctypes.cdll.LoadLibrary("<...>")
l = ["Hello", "world"]
# 1
dll.combineWords1.argtypes = [ctypes.POINTER(VARIANT)]
dll.combineWords1.restype = ctypes.c_char_p
obj = VARIANT(l)
dll.combineWords1(obj)
#WindowsError: [Error -532462766] Windows Error 0xE0434352
# 2
dll.combineWords2.argtypes = [ctypes.POINTER(VARIANT)]
dll.combineWords2.restype = ctypes.c_char_p
obj = VARIANT(l)
dll.combineWords2(obj)
# WindowsError: [Error -532462766] Windows Error 0xE0434352
# 3
dll.combineWords3.argtypes = [ctypes.POINTER(VARIANT)]
obj = VARIANT(l)
dll.combineWords3(obj)
#WindowsError: [Error -532462766] Windows Error 0xE0434352
# 4
dll.combineWords4.argtypes = [ctypes.POINTER(VARIANT)]
obj = VARIANT(l)
dll.combineWords4(obj)
#WindowsError: [Error -532462766] Windows Error 0xE0434352
1 ответ
Решение
Вы можете объявить сторону C# следующим образом:
[DllExport("combinewords", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPWStr)] // matches python's c_wchar_p
public static string CombineWords(object obj) // object matches python's VARIANT
{
var array = (object[])obj; // if obj is an array, it will always be an array of object
return string.Join(", ", array);
}
И сторона Python, как это:
import ctypes
from ctypes import *
from comtypes.automation import VARIANT
dll = ctypes.cdll.LoadLibrary("exported") # the dll's name
dll.combinewords.argtypes = [VARIANT] # python VARIANT = C# object
dll.combinewords.restype = ctypes.c_wchar_p
# create a VARIANT from a python array
v = VARIANT(["hello", "world"])
print(dll.combinewords(v))
Примечание: я использовал декларацию Unicode, которая лучше. Анси ушел в прошлое.