#python #c# #ironpython #dynamic-language-runtime
Вопрос:
Я хочу, чтобы приложение на python передавало общий список в мой код на C#. Я создал демонстрационное приложение, которое дублирует проблему, которую я вижу.
У меня есть этот код python (Python 2.7) MainApp.py
, который вызывает библиотеку DLL C# (.NET 4.7):
import clr, sys
sys.path.append(r"C:PathToMyProjectClassLibrary1binDebug")
clr.AddReference(r"C:PathToMyProjectClassLibrary1binDebugClassLibrary1.dll")
from ClassLibrary1 import Class1
class Person:
def __init__(self, Name):
self.Name = Name
myclass = Class1()
nameList = []
nameList.append(Person("Joe"))
nameList.append(Person("Mary"))
nameList.append(Person("Chris"))
result = myclass.SayHello(nameList)
print(result)
Обратите внимание, что у меня есть список Person
объектов nameList
, которые я пытаюсь передать. Вот код на C# :
using System.Collections.Generic;
namespace ClassLibrary1
{
public class Class1
{
public string SayHello(List<dynamic> names)
{
return $"Hello, {names.Count} people!";
}
}
}
SayHello
Метод принимает параметр List<dynamic>
. Однако при запуске я получаю следующую ошибку >python MainApp.py
:
Обратная связь (последний последний вызов): Файл «.MainApp.py», строка 20, в результате = myclass.Ошибка типа sayHello(список имен): Ни один метод не соответствует заданным аргументам для sayHello: (<тип «список»>)
Ответ №1:
Я решил эту проблему с помощью следующего кода:
MainApp.py:
import clr, sys
sys.path.append(r"C:ProjectstempClassLibrary1binDebug")
clr.AddReference(r"C:ProjectstempClassLibrary1binDebugClassLibrary1.dll")
from ClassLibrary1 import Class1
from ClassLibrary1 import Person
myclass = Class1()
nameList = []
nameList.append(Person("Joe"))
nameList.append(Person("Mary"))
nameList.append(Person("Chris"))
result = myclass.SayHello(nameList)
print(result)
Класс 1.cs:
namespace ClassLibrary1
{
public class Class1
{
public string SayHello(dynamic[] names)
{
foreach (var item in names)
{
System.Console.WriteLine(item.Name);
}
return $"Hello, {names.Length} people!";
}
}
public class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; set; }
}
}
Первое, что я сделал, это изменил SayHello
тип параметра с List<dynamic>
на dynamic[]
.
public string SayHello(dynamic[] names)
Это исправило ошибку типа, но я начал получать новое сообщение:
Необработанное исключение: Система.Отражение.Исключение TargetInvocationException: Исключение было вызвано целью вызова. —> Система.Исключение AccessViolationException: Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена.
на Python.Время выполнения.Время выполнения.PyObject_GetAttrString(указатель IntPtr, имя строки) в Python.Время выполнения.ПиОбъект.GetAttr(имя строки) в Python.Время выполнения.ПиОбъект.TryGetMember(связыватель GetMemberBinder, объект и результат) на сайте вызова.Цель(Закрытие , место вызова , объект ) в Системе.Динамический.Обновленыелегаты.UpdateAndExecute1[T0,TRet](сайт сайта вызова, T0 arg0) в ClassLibrary1.Class1.sayHello(Имена объектов []) в C:Projectscsharp-nine-cookbookcsharp-nine-cookbookCSharp9CookbookClassLibrary1Class1.cs:line 11 — Конец трассировки внутреннего стека исключений — в System.RuntimeMethodHandle.Вызов метода(Цель объекта, аргументы объекта [], Сигнатура sig, логический конструктор) в Системе.Отражение.RuntimeMethodInfo.UnsafeInvokeInternal(Объект obj, параметры объекта [], аргументы объекта []) в системе.Отражение.RuntimeMethodInfo.Вызов(Object obj, BindingFlags invokeAttr, Связующее связующее, параметры объекта [], культура CultureInfo)
на Python.Время выполнения.Переплетчик методов.Вызовите(IntPtr inst, IntPtr args, IntPtr kw, информация о базе методов, методинфо[] методинфо) на Python.Время выполнения.Методобъект.Вызовите(цель IntPtr, аргументы IntPtr, параметры IntPtr, информация о базе методов) в Python.Время выполнения.Привязка метода.tp_call(IntPtr ob, IntPtr args, IntPtr kw)
Очевидно, IronPython не позволил мне передавать пользовательские типы с python на C#. Чтобы исправить это, я добавил Person
класс в код C# :
public class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; set; }
}
Затем я удалил пользовательский класс Person из кода python и сослался на него в коде C# :
from ClassLibrary1 import Person
После этого все работало нормально.