C ++ / C # Проблемы с плавающей точкой - PullRequest
2 голосов
/ 05 мая 2011

У меня проблема при попытке прочитать структуру из C ++ в C #.Я делал это несколько раз, и это работало всегда, но я никогда не использовал числа с плавающей запятой.

Это структуры, которые я использую на стороне C #:

[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;
}

Это структуры, которые я используюна стороне C ++:

    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;
    };

Теперь часть C #, которая использовалась для получения данных:

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);

И, наконец, часть, которая используется для извлечения данных (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;
}

Номер misc верен при чтении его в C #, и Консоль сообщает мне правильные числа, но все числа с плавающей точкой повреждены, и когда я получаю разные числа в C ++ и C #.В любом случае, разница в том, чтобы принять это.(Получил 340 в C ++ и около 0.xxxxxxx в C #).

Любая помощь будет приветствоваться.Спасибо.

Ответы [ 2 ]

3 голосов
/ 05 мая 2011

Может ли это быть из-за того, что .Net Boolean отличается от размера вашей реализации C ++ bool?Я думаю, что VC ++ использует 1 байт для bool, в то время как .Net использует 2 или 4 байта для System.Boolean.

Попробуйте определить IsValid как Byte вместо Boolean и посмотрите, работает ли он.

Я думаю, вы также можете добавить атрибут MarshalAs перед Boolean, чтобы заставить его маршалировать как 1-байтовый:

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

Но я не уверен, что он будет работать в вашем случае,поскольку вы напрямую используете указатели, а не маршалинг.

0 голосов
/ 05 мая 2011

В CLI значение bool определяется как 4 байта, однако sizeof сообщает, что он равен 1 байту.Все 0 представляют Ложь, все остальное считается Истиной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...