问题
I have come across a problem with IronPython that I can't solve. I need to call a function that takes a parameter of type array to value-type. The function-signature (in C++/CLI notation) is this:
static int PLGServiceInterface::PLGService::MapLowSpeedRealtimeNames(cli::array<System::String ^> ^ SignalNames, int timeout_ms, cli::array<PLGServiceInterface::LVCluster_1> ^% Channels, System::String ^% ReportText)
When I call the function from IronPython
import clr
clr.AddReferenceToFileAndPath('PLGServiceAPI.dll')
from System import String, Array
from PLGServiceInterface import PLGService, LVCluster_1
outtext = clr.Reference[String]()
outdata = clr.Reference[Array[LVCluster_1]]()
PLGService.MapLowSpeedRealtimeNames(('hello', 'world'), 300, outdata, outtext)
I get the following error
Traceback (most recent call last):
File "test2.py", line 9, in <module>
TypeError: expected StrongBox[Array[LVCluster_1]], got StrongBox[Array[LVCluster_1]]
The error message is not very helpful but I assume the problem is that "outdata" is an array containing value types instead of reference types. Apparently IronPython doesn't know how to do the boxing in that case.
With C++/CLI I can use the function just fine:
using namespace System;
using PLGServiceInterface::LVCluster_1;
using PLGServiceInterface::PLGService;
int main(array<System::String ^> ^args)
{
array<LVCluster_1> ^outdata;
array<String^> ^names = gcnew array<String^>{"one", "two"};
String ^o;
PLGService::MapLowSpeedRealtimeNames(names, 300, outdata, o);
Console::WriteLine(o);
Console::Read();
return 0;
}
I assume if the function would instead expect an array of references
array<LVCluster_1 ^> ^outdata
I could call it with IronPython.
Is there any way to make this work with IronPython? By the way, the assembly was created with LabView and LVCluster_1 is a LabView-Cluster (structure).
Edit: The Intermediate Language signature of MapLowSpeedRealtimeNames is this:
.method public hidebysig static int32 MapLowSpeedRealtimeNames(string[...] SignalNames,
int32 timeout_ms,
[out] valuetype PLGServiceInterface.LVCluster_1[...]& Channels,
[out] string& ReportText) cil managed
Does anybody know what the meaning of the 3 dots in the array brackets is? When I compile a function that takes an array in C++/CLI, I only get the opening and closing brackets without the dots in between.
These dots seem suspicious to me because I also get the TypeError when calling a method that takes an out-parameter of type array of double(float64):
.method public hidebysig static int32 ReadVariables(string[...] SignalNames,
int32 timeout_ms,
[out] string& ReportText,
[out] float64[...]& Data) cil managed
Generates the error
TypeError: expected StrongBox[Array[float]], got StrongBox[Array[float]]
回答1:
Have you tried using Array.CreateInstance(LVCluster_1, length) to create the array? See example below:
outdata = Array.CreateInstance(LVCluster_1, 2)
The code above works for me, but my c++/cli function signature don't use the tracking reference (%). So if I were to re-write your function signature it would look like:
static int PLGServiceInterface::PLGService::MapLowSpeedRealtimeNames(cli::array<System::String ^> ^ SignalNames, int timeout_ms, cli::array<PLGServiceInterface::LVCluster_1> ^ Channels, System::String ^ ReportText)
来源:https://stackoverflow.com/questions/29305150/ironpython-how-to-call-a-function-that-expects-an-array-of-value-types