C
C#rick_o_max

✅ 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.
R
rick_o_max510d ago
This is my CPP class:
typedef struct TModel
{
char* Name;
bool Used;
Vector3 LocalPosition;
Quaternion LocalRotation;
Vector3 LocalScale;
bool Visibility;
//void* Parent;
//void* Children;
//void* Bones;
//bool IsBone;
//void* GeometryGroup;
//void* BindPoses;
//void* MaterialIndices;
//void* UserProperties;
} Model;
typedef struct TModel
{
char* Name;
bool Used;
Vector3 LocalPosition;
Quaternion LocalRotation;
Vector3 LocalScale;
bool Visibility;
//void* Parent;
//void* Children;
//void* Bones;
//bool IsBone;
//void* GeometryGroup;
//void* BindPoses;
//void* MaterialIndices;
//void* UserProperties;
} Model;
This is my C# class:
[StructLayout(LayoutKind.Sequential, CharSet = Interoperability.DefaultCharSet)]
public class Model// : IModel
{
[field: MarshalAs(UnmanagedType.LPStr)]
public string Name { get; set; }
[field: MarshalAs(UnmanagedType.U1)]
public bool Used { get; set; }
public Vector3 LocalPosition { get; set; }
public Quaternion LocalRotation { get; set; }
public Vector3 LocalScale { get; set; }
[field: MarshalAs(UnmanagedType.U1)]
public bool Visibility { get; set; }
//public IModel Parent { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<IModel> Children { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<IModel> Bones { get; set; }
//[field: MarshalAs(UnmanagedType.U1)]
//public bool IsBone { get; set; }
//public IGeometryGroup GeometryGroup { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public Matrix4x4[] BindPoses { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<int> MaterialIndices { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public Dictionary<string, object> UserProperties { get; set; }
}
[StructLayout(LayoutKind.Sequential, CharSet = Interoperability.DefaultCharSet)]
public class Model// : IModel
{
[field: MarshalAs(UnmanagedType.LPStr)]
public string Name { get; set; }
[field: MarshalAs(UnmanagedType.U1)]
public bool Used { get; set; }
public Vector3 LocalPosition { get; set; }
public Quaternion LocalRotation { get; set; }
public Vector3 LocalScale { get; set; }
[field: MarshalAs(UnmanagedType.U1)]
public bool Visibility { get; set; }
//public IModel Parent { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<IModel> Children { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<IModel> Bones { get; set; }
//[field: MarshalAs(UnmanagedType.U1)]
//public bool IsBone { get; set; }
//public IGeometryGroup GeometryGroup { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public Matrix4x4[] BindPoses { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public IList<int> MaterialIndices { get; set; }
//[field: MarshalAs(UnmanagedType.LPStruct)]
//public Dictionary<string, object> UserProperties { get; set; }
}
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.
W
WhiteBlackGoose510d ago
IModel is a managed type, since it's (probably) an interface
R
rick_o_max510d ago
I just realized I haven't added the LPStruct to the Parent member, let me see if that makes any difference
W
WhiteBlackGoose510d ago
I have no idea if it will help
R
rick_o_max510d ago
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?
W
WhiteBlackGoose510d ago
doesn't make sense to me, since GC is moving
R
rick_o_max510d ago
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
W
WhiteBlackGoose510d ago
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?
R
rick_o_max510d ago
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
W
WhiteBlackGoose510d ago
honestly, idk either I usually do it all manually to ensure it works as I expect but it's probably a bad advice
R
rick_o_max510d ago
Wdym with manually? Looks like I can pass the entire struct as pointer with Marshal.StructureToPtr That requires creating a buffer, tho
W
WhiteBlackGoose510d ago
manually as in, with structs, pointers, and 0 managed objects whatsoever
R
rick_o_max510d ago
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
A
Anton510d ago
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
R
rick_o_max510d ago
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...hmm
A
Anton510d ago
generally 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
R
rick_o_max509d ago
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
A
Accord508d ago
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.
Want results from more Discord servers?
Add your server
More Posts
❔ Set item to null inside a listHey! I am trying to remove some items from a JSON object (created like `var model = new ObjectModel{Refactoring long if statement that checks for user rolesHi, I'm trying to find a cleaner way of refactoring this if code block that checks for each user rol❔ IEnumerable and dependency injectionif i want to loop enumerable from DI multiple times ``` var foos = services.GetRequiredService<IEnum❔ How did you learn . NET ?Books /youtube/udemy /other courses, what resources made you learn .NET to use as your job as web de✅ Is it possible to disable these properties on EF6? Web API 2 project, multi-layered, NF472SCENARIO - Solution type is NET Framework 4.7.2 (it is, what it is). - I have this project, I'm cons✅ This EntityFramework query can not be translated for SQLiteThe issue lies within `Intersect`. The point of the query is to fetch the current user, and to popul✅ Detect Network RequestI want make service that detect all connection to specific domain or ip? And if this request contain❔ CORS errorHello, I have Cors error on my project. I add Addpolicy in my configureServices and also add app.Us❔ Ambiguities? How?Idk how i can resolve this i don't see the problem✅ How can I get rid of this annoying pointer thing in the first row, datagridview winforms^✅ How can I use a row header of a datagridview to display the row number instead of being empty?^✅ How can i properly display this datagridviewHow can i get rid of the row select thing on the left (just white space)✅ I am trying to output a 2D array to a datagridview, but it is not outputting correctlyIt is saying System.Int32[]✅ Task not returning and stopping programHey, I am currently trying to start one task for every string in the list, but this isn't working an❔ DbContextCan i use this in a non-asp area like for example, a simple program to make few tables using DbSet✅ The specified deps.json does not exist while scaffolding DBI am going through a tutorial to create a Web API app with ASP.NET6 and MySql. I wanted to scaffold ❔ C sharp object reference errorI am trying to reference an object that I'm displaying on PageHeader.xaml and I keep getting this erInteroperability issues (PInvoke)Hi! I'm calling a native CPP library and retrieving a struct by reference which returns a struct con❔ SKIA SHARP PROBLEMError: ```cmd Dec 02 16:05:22 mourashop shopmoura-api-app[3847595]: Unhandled exception. System.Argu❔ FluentAssertions excluding collection elementsI have two IEnumerable<Claim> tmp1, tmp2 and I want to see if they are equal, except for the claims