2013-10-25 1 views
3

Я пытаюсь использовать .NET dll в Python. В языке .NET метод требует передать ему 2 массивов путем ссылки, которые он затем модифицирует:Как использовать метод .NET, который модифицируется в Python?

public void GetItems(
out int[] itemIDs, 
out string[] itemNames 
) 

Как я могу использовать этот метод в Python с использованием Python для модуля .NET?

Редактировать: Забыл упомянуть об этом в CPython, а не IronPython.

Дополнительная информация. Когда я делаю следующее:

itemIDs = [] 
itemNames = [] 
GetItems(itemIDs, itemNames) 

Я получаю выход, как:

(None, <System.Int32[] at 0x43466c0>, <System.String[] at 0x43461c0>) 

Мне просто нужно выяснить, как преобразовать их обратно в типы питона?

+1

Почему вы хотите преобразовать их обратно в типы Python, а не просто использовать их? – abarnert

+0

@abarnet Так как вы сделали такую ​​отличную работу в своем ответе ниже, я собираюсь прокомментировать там. – Jonno

ответ

6

PythonNet не документирует это так же четко, как IronPython, но делает почти то же самое.

Итак, давайте посмотрим на документацию IronPython для ref and out parameters:

The Python language passes all arguments by-value. There is no syntax to indicate that an argument should be passed by-reference like there is in .NET languages like C# and VB.NET via the ref and out keywords. IronPython supports two ways of passing ref or out arguments to a method, an implicit way and an explicit way.

In the implicit way, an argument is passed normally to the method call, and its (potentially) updated value is returned from the method call along with the normal return value (if any). This composes well with the Python feature of multiple return values…

In the explicit way, you can pass an instance of clr.Reference[T] for the ref or out argument, and its Value field will get set by the call. The explicit way is useful if there are multiple overloads with ref parameters…

Есть примеры для обоих. Но адаптировать его к вашему конкретному случаю:

itemIDs, itemNames = GetItems() 

Или, если вы действительно хотите:

itemIDsRef = clr.Reference[Array[int]]() 
itemNamesRef = clr.Reference[Array[String]]() 
GetItems(itemIDs, itemNames) 
itemIDs, itemNames = itemIDsRef.Value, itemNamesRef.Value 

CPython с использованием PythonNet делает в основном то же самое. Простой способ сделать параметры out - это не передавать их и принимать их как дополнительные возвращаемые значения, а для параметров ref передавать входные значения в качестве аргументов и принимать выходные значения в качестве дополнительных возвращаемых значений. Также как неявное решение IronPython. (За исключением того, что функция void с параметрами ref или out всегда возвращает None до аргументов ref или out, даже если это не будет в IronPython.) Вы можете легко понять это, проверив возвращаемые значения. Таким образом, в вашем случае:

_, itemIDs, itemNames = GetItems() 

Между тем, тот факт, что это происходит, чтобы быть массивы не делает вещи тяжелее. Как объясняет the docs, PythonNet предоставляет итерируемый интерфейс для всех коллекций IEnumerable, а также протокол последовательности для Array. Таким образом, вы можете сделать это:

И Int32 и String объекты будут преобразованы в родной int/long и str/unicode объекты так же, как если бы они были возвращены непосредственно.

Если вы действительно хотите явно преобразовать их в собственные значения, вы можете. map или понимание списка даст вам список Python из любого итеративного файла, включая обертку PythonNet вокруг Array или других IEnumerable.И вы можете явно сделать long или unicode из Int32 или String, если вам нужно. Итак:

itemIDs = map(int, itemIDs) 
itemNames = map(unicode, itemNames) 

Но я не вижу много преимуществ, чтобы сделать это, если не нужно, например, предварительно проверить все значения, прежде чем использовать любой из них.

+1

Спасибо, к сожалению, я забыл упомянуть, что я использую CPython, а не IronPython. – Jonno

+1

@Jonno: ОК, отредактирован, чтобы показать PythonNet, а также IronPython. – abarnert

+1

@abernet Я создаю некоторую документацию о том, как использовать эту DLL в CPython. Я думаю, что будут случаи, когда пользователь захочет использовать встроенные атрибуты объектов python, которые не будут доступны в противном случае. Оказывается, Python.Net возвращает объекты python, если возвращаемые значения являются строками, int и т. Д. Только если возвращаемый объект является массивом, он не преобразует. Я использовал понимание списка в своей документации как пример того, как преобразовать массив в список (в то же время преобразуя тип элементов). Спасибо за идею карты. _, itemIDs, itemNames = GetItems() Я получаю следующую ошибку:: TypeError – Jonno

1

мне удалось использовать метод BOOL XferData (исе байты [] ЬиЙ, исй INT LEN) из C# библиотеки CyUSB.dll со следующим кодом:

>>> xferLen = 2; 

>>> outData=[10, 0] 

>>> inData=[] 

>>> n, outData, xferLen = XferData(outData, xferLen) 

>>> print n, outData[0], outData[1], xferLen 

True 10 0 2 

Надеется, что это поможет кому-то.

Смежные вопросы