C++/C# Float issues

夙愿已清 提交于 2019-12-11 02:51:58

问题


I have a problem when trying to read a struct from C++ in C#. I did this more times and it worked always, but i never used floating point numbers.

These are the structs i use on the C# side:

[StructLayout(LayoutKind.Sequential)]
public struct ImageData
{
    public UInt32 Width;
    public UInt32 Height;
    public UInt32 Length;
    public IntPtr PixelPointer;
}
[StructLayout(LayoutKind.Sequential)]
public struct UserData
{
    public UInt32 misc;
    public Boolean IsValid;
    public VirtualPosition RightHand;
    public VirtualPosition LeftHand;
    public VirtualPosition Head;
}
[StructLayout(LayoutKind.Sequential)]
public struct VirtualPosition
{
    public Position3D RealPosition;
    public Position3D ProjectedPosition;
}
[StructLayout(LayoutKind.Sequential)]
public struct Position3D
{
    public float X;
    public float Y;
    public float Z;
}

This are the structs i use on the C++ side:

    typedef struct XnVector3D
    {
       XnFloat X;
       XnFloat Y;
       XnFloat Z;
    } XnVector3D;
    class VirtualPosition {
    public:
        XnVector3D RealPosition;
        XnVector3D ProjectedPosition;

        VirtualPosition(void) { }
        VirtualPosition(XnVector3D real, XnVector3D projected) {
            RealPosition = real;
            ProjectedPosition = projected;
        }
    };

    class UserData
    {
        public:
        int misc; // Misc number to check if i have the correct pointer ( debug only )
        bool Valid;
        VirtualPosition RightHand;
        VirtualPosition LeftHand;
        VirtualPosition Head;
    };

Now the C# part which has been used to get the data:

public unsafe UserData GetUserData(UInt32 user)
{
    IntPtr pos = GetData(_Index, user);
    UserData* ptr = ((UserData*)pos.ToPointer());
    UserData result = *ptr;
    return result;
}
[DllImport("KinectNative.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetData(Int32 index, UInt32 user);

And finally the part which is used to retrieve data( C++ ):

EXPORT UserData* GetData(int index, XnUserID user) 
{
    if (_LastData != NULL) _LastData->~UserData();
    system("cls");
    _LastData = new UserData(_Context->GetDevice(index)->GetData(user));
    std::cout << "X: " << (int)_LastData->Head.ProjectedPosition.X << " Y:" << (int)_LastData->Head.ProjectedPosition.Y << std::endl;
    return _LastData;
}

The misc number is correct when reading it in C# and the Console tells me the correct numbers, but all floats are corrupted and when i get different numbers in C++ and C#. Anyway the difference is to large to accept it. ( Got 340 in C++ and around 0.xxxxxxx in C# ).

Any help would be welcome. Thanks.


回答1:


Could it be because the .Net Boolean is not the same size as your C++ implementation bool? I think VC++ uses 1 byte for bool while .Net uses 2 or 4 bytes for System.Boolean.

Try defining IsValid as Byte instead of Boolean and see if it works.

I think you can also add the MarshalAs attribute before Boolean to force it to be marshaled as 1-byte:

[StructLayout(LayoutKind.Sequential)]
public struct UserData
{
    public UInt32 misc;
    [MarshalAs(UnmanagedType.U1)]
    public Boolean IsValid;
    public VirtualPosition RightHand;
    public VirtualPosition LeftHand;
    public VirtualPosition Head;
}

But I'm not sure it's going to work in your case, since you directly use pointers, not marshaling.




回答2:


In CLI, a bool is defined as being 4 Bytes, however sizeof would report it as being 1 Byte. All 0's represents False, anything else is taken to be True.



来源:https://stackoverflow.com/questions/5897567/c-c-float-issues

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!