Search code examples
pythonc++.netpython.netpython-cffi

Passing C objects (CFFI) to .NET (Pythonnet)


Using Python, I would like to use C or C++ structs defined in a dll and pass them to .NET dll written in C#. The C or C++ dll is added using cffi, the .NET one is loaded using pythonnet.

The definition of the structs is identical in both dlls.

Here is a simple example for float2, of course reality is more complex :)

import sys
import clr
import numpy as np

sys.path.append('my_dot_net.dll')

#load the .NET dll
clr.AddReference("dot_net_dll")

from cffi import FFI
ffi = FFI()

#load C dll
lib = ffi.dlopen('c.dll')

# definition of a simple struct, there is an identical one in .NET
ffi.cdef('''typedef struct
            {
                float x;
                float y;
            } float2;''')

from dot_net_namespace import float2

#float2 type in dot net
dotnet_float2 = float2()
dotnet_float2.x = 1.0
dotnet_float2.y = 2.0

#float2 in the c dll
c_float2 = ffi.new("float2 *") # usually numpy array
c_float2.x  = 1.0
c_float2.y  = 2.0

Now I would like to e.g. create an array of the .NET data type or assign objects to the a struct available in .NET and assign the C type objects to that:

dot_net_float2_array = System.Array.CreateInstance(dot_net_float2, 100)
dot_net_float2_array[0] = c_float2 #does not work

dot_net_struct.xy = c_float2 #does not work

I get different error messages like

TypeError: Cannot convert <cdata 'float2[]' owning 8240 bytes> to dot_net_namespace.float2[]

'_cffi_backend.CDataOwn' value cannot be converted to dot_net_namespace.float2

TypeError: initializer for ctype 'float2' must be a list or tuple or dict or struct-cdata, not float2

I have no idea how to solve this. The real code I am working on should use structs that hold arrays of structs and I can't even get this simple example to run :)

Of course it is possible to copy the structs field by field, but is there a more convenient way? Is this possible at all?

Might it be possible to use ffi.cast or ffi.buffer?


Solution

  • I ended up passing pointers to .NET. They can be casted as described in my other question here. The full answer should become visible once my edit is reviewed and accepted.

    How to cast a pointer to a Python cffi struct to System.IntPtr (.NET)?

    After this Marshal.PtrToStructure Method (IntPtr, Type) is used to reassemble the structs in .NET.