✅ Interoperability between incompatible types
Hi!
I'm trying to pass a class back-and-forth from C# to CPP.
This class contains some members that I can't and don't need to translate to CPP types, but when I add these members to my interop classes, the application exits with a fatal error.
18 Replies
This is my CPP class:
This is my C# class:
If I use the classes as they are, it works fine, but if I uncomment the lines on C# and CPP, the application crashes. It might have something to do with the way these references are passed to CPP. I don't need their types in CPP, I just need to keep a reference to them.
IModel is a managed type, since it's (probably) an interface
I just realized I haven't added the LPStruct to the Parent member, let me see if that makes any difference
I have no idea if it will help
No, it doesn't
Yes, it is a managed type
But can't I keep a reference to it as a
void*
when passing the struct to cpp?doesn't make sense to me, since GC is moving
I don't need CPP to touch these commented out fields, but I have to keep them "alive" while passing the struct/class back and forth
hmm
I'll probably have to wrap the fields I can interop inside another class
if you need to keep them alive, just use GC.KeepAlive
call it after your native method
although it doesn't make sense to me
bc if you don't want to touch them but want to keep them alive... it's either that C++ does touch them, or you just have no reference to it afterwards, but then why keep alive?
I don't want to create the structs on CPP heap, so I'm creating everything on C# and passing the objects to CPP. CPP can change the fields, but won't create anything (besides strings allocations)
CPP calls a C# callback
C# creates the objects and send the pointer back to CPP
CPP modifies the objects
But well, thinking better
I'm still not 100% sure about the best way to handle that
honestly, idk either
I usually do it all manually to ensure it works as I expect
but it's probably a bad advice
Wdym with manually?
Looks like I can pass the entire struct as pointer with
Marshal.StructureToPtr
That requires creating a buffer, tho
manually as in, with structs, pointers, and 0 managed objects whatsoever
The only problem is I have to use some managed classes, and part of the classes holding these other classes must come from CPP
I know I can make it field by field, by calling CPP methods and creating some system to track the classes by id or something like that
But that is a lot of work
check out the actual layout of your class
layout sequential would put reference types on top anyway
if I remember correctly
you need layout explicit for it to actually apply
from the docs:
For non-blittable types, it controls the layout when the class or structure is marshaled to unmanaged code, but does not control the layout in managed memory. Use the attribute with LayoutKind.Explicit to control the precise position of each data member. This affects both managed and unmanaged layout, for both blittable and non-blittable types.
by non-blittable they mean types with fields of reference type
or show us how you marshal the object
Interesting
Is there a way to set a type blitting as a pointer only?
Bc the only thing I need, is keep the same structure from the C# class in CPP
I don't need CPP to touch some fields
There are classes I can't interop anyway, like
Dictionary
instances from my C# classes
If there is no way to do that, I'll have to create simpler structures to work on CPP, and wrap these in the final C# classes which contains all the properties I need
The point is that, I don't want to create huge wrappers around my classes or using Swig to do that
Can't use CLI either
So my idea is letting C# handle the objects creation while CPP only fires C# callbacks
Well, I guess I don't need to read any specific data form the C# classes in CPP anyway
So using callbacks might work fine
So, looks like it should work
But Idk if what I'm doing is "Ilegal", like
I'm passing a struct containing all my callbacks to CPP
But when CPP calls these callbacks, program crashes
It used to work fine when these callbacks were outside the struct
But I use the struct to pass all callbacks at once
I'm passing a CallbackData
struct by val to CPP, it seems to get the values right, but throws an error when calling any callback method
Nvm, values are messed up somehow...hmmgenerally use properties if possible, then you don't have to care about the layout. You just get a pointer to some memory on the cpp side, and then use properties to work with that
that's generally how library abstraction works in C too
they pass around an opaque pointer (handle), and have a bunch of operations defined for it
here you'd just have the operations be methods, which is arguably easier to work with
Unity does it the other way — they define the layout on the cpp side, and have wrappers with properties on the C# side
I ended up doing everything differently
Since I just care about the final objects created in C#
I pass a series of callbacks to C
So it can pass the data C# needs to create and update the structures
I'm not sure about C to C# callback performance, tho
But it is working as expected
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.