I'm struggling to export a C++ struct data to C#.
Say I have the following structure representing a 3-floating-points vector:
// C++
struct fvec3
{
public:
float x, y, z;
fvec3(float x, float y, float z) : x(x), y(y), z(z) { }
};
// C#
[StructLayout(LayoutKind.Sequential)]
struct fvec3
{
public float x, y, z;
public fvec3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
Now, if I wanted to use a fvec3
from C# to C++, I can use the following without a problem:
// C++
__declspec(dllexport) void Import(fvec3 vector)
{
std::cout << vector.x << " " << vector.y << " " << vector.z;
}
// C#
[DllImport("example.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Import(fvec3 vector);
...
Import(new fvec3(1, 2, 3)); // Prints "1 2 3".
The problem now is to do the opposite: return a C++ fvec3
to C#. How can I do this?
I've seen many C# implementations use something along the lines of this:
// C#
[DllImport("example.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Export(out fvec3 vector);
...
fvec3 vector;
Export(out vector); // vector contains the value given by C++
But how do I write the C++ Export
function?
I tried everything I could think about for both the signature and the body:
// Signatures:
__declspec(dllexport) void Export(fvec3 vector)
__declspec(dllexport) void Export(fvec3* vector)
__declspec(dllexport) void Export(fvec3& vector)
// Bodies (with the pointer variants)
vector = fvec3(1, 2, 3);
memcpy(&fvec3(1, 2, 3), &vector, sizeof(fvec3));
*vector = new fvec(1, 2, 3);
Some of these have no effet, some return garbage values, and some cause crashes.
ref
and out
parameters are usually matched with pointer arguments.
Try this:
__declspec(dllexport) void Export(fvec3 *vector)
{
*vector = fvec3(1, 2, 3);
}
(Untested)
Alternatively, you should be able to simply return a fvec3
from your function:
// C++
__declspec(dllexport) fvec3 Export(void)
{
return fvec3(1, 2, 3);
}
// C#
[DllImport("example.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern fvec3 Export();
...
fvec3 vector = Export();
(Untested)