Darckense Darckense - 1 month ago 16
C# Question

How to use Python and .NET/C# to automatise Princeton Instruments LightField

I want to use Python to control a proprietary spectroscopic software (Princeton Instruments LightField). I have a LightField automation example using Matlab. The example use .NET to control LightField using provided DLLs.

I used pythonnet to load the DLLs into Python, but I failed to communicate with LightField.

Here is a (non-)working example :

import sys
sys.path.append(r"C:\Program Files\Princeton Instruments\LightField")
sys.path.append(r"C:\Program Files\Princeton Instruments\LightField\AddInViews")

import clr
clr.AddReference('PrincetonInstruments.LightFieldViewV4')
clr.AddReference('PrincetonInstruments.LightField.AutomationV4')
clr.AddReference('PrincetonInstruments.LightFieldAddInSupportServices')

import PrincetonInstruments.LightField.AddIns as AddIns
from PrincetonInstruments.LightField.Automation import Automation

instance = Automation(True,[])


And here is the error message :

File "D:/python/test_lightfield.py", line 21, in <module> instance = Automation(True,[])
TypeError: no constructor matches given arguments


However, when I look at the beginning of help(Automation) :

help(Automation)
Help on class Automation in module PrincetonInstruments.LightField.Automation:

class Automation(System.Object)
| Void .ctor(Boolean, System.Collections.Generic.List`1[System.String])
|
| Method resolution order:
| Automation
| System.Object
| builtins.object
|
| Methods defined here:
|
| __call__(self, /, *args, **kwargs)
| Call self as a function.


or the relevant Matlab example file :

out.automation = PrincetonInstruments.LightField.Automation.Automation(visible,[]);


It looks like I instantiated the Automation class with valid arguments (a boolean and an empty string).
I don't have much documentation apart my Matlab sample file.

What am I doing wrong ?

Answer

Check for supported constructor signatures in __overloads__, e.g.:

>>> import clr
>>> from System import Decimal
>>> Decimal.__overloads__
System.Decimal(Int32[])
System.Decimal(UInt64)
System.Decimal(UInt32)
System.Decimal(Int64)
System.Decimal(Int32)
System.Decimal(Single)
System.Decimal(Double)
System.Decimal(Int32, Int32, Int32, Boolean, Byte)

EDIT:

Convert your second argument to .NET type (System.Collections.Generic.List[System.String]) before passing it. Auto-conversion of containers is not supported in pythonnet yet.

EDIT:

Here is how to do this:

In C#:

using System;
using System.Collections.Generic;

namespace ListInConstr
{
    public class ListInConstr
    {
        public ListInConstr(bool test1, List<String> test2)
        {

        }
    }
}

In Python:

>>> import clr
>>> import sys
>>> sys.path.append(r"C:\Debug")
>>> clr.AddReference("ListInConstr")
<System.Reflection.RuntimeAssembly object at 0x02849E50>
>>> from ListInConstr import ListInConstr
>>> ListInConstr.__overloads__
ListInConstr.ListInContr(Boolean, System.Collections.Generic.List`1[System.String])
>>> from System.Collections.Generic import List
>>> from System import String
>>> arg2=List[String]() #do not add elements here
>>> ListInConstr(True,arg2)
<ListInConstr.ListInConstr object at 0x0284E890>
>>>