Может ли непосредственный доступ к переменной (а не с помощью указателя и разыменования) дать разные значения? - PullRequest
2 голосов
/ 15 апреля 2011

Я знаю, что это странный вопрос, и я рискую показать свою зелень, но я тут рву свои волосы.

У меня есть пример C ++, который работает, как ожидалось. Вот фрагмент этой надоедливой части:

BIRDFRAME frame;
birdGetMostRecentFrame(GROUP_ID,&frame);
BIRDREADING *bird_data;
bird_time=frame.dwTime;
for(FBBloop=FBBstart; FBBloop<FBBend; FBBloop++ )
{                   
    bird_data = &frame.reading[FBBloop];
    // Do stuff
}

Обратите внимание, что bird_data является указателем и ему присвоен адрес frame.reading[FBBloop]. Мое приложение написано на C # и поэтому не имеет этого указателя malarkey. Соответствующий бит выглядит так:

FlockOfBirds.BIRDFRAME frame = new FlockOfBirds.BIRDFRAME();
FlockOfBirds.birdGetMostRecentFrame(1, ref frame);
Console.WriteLine("T:{0}",frame.dwTime.ToString());
FlockOfBirds.BIRDREADING reading;
for (int k = 1; k <= sysconf.byNumDevices; k++)
{
    reading = frame.readings[k];
    Console.WriteLine("  [{0}][{1}][{2}]", reading.position.nX.ToString(), reading.position.nY.ToString(), reading.position.nZ.ToString());
}

Проблема в том, что в примере C # только reading[1] имеет значимые данные. В примере на C ++ и bird_data[1], и bird_data[2] имеют хорошие данные. Как ни странно, reading[2-n] не все имеют нулевые значения, но кажутся случайными и постоянными. Вот как выглядит вывод приложения C #:

T:17291325
  [30708][-2584][-5220]
  [-19660][1048][-31310]

T:17291334
  [30464][-2588][-5600]
  [-19660][1048][-31310]

T:17291346
  [30228][-2600][-5952]
  [-19660][1048][-31310]

T:17291354
  [30120][-2520][-6264]
  [-19660][1048][-31310]

T:17291363
  [30072][-2388][-6600]
  [-19660][1048][-31310]

Обратите внимание, что верхний триплет каждой записи немного отличается от триплетов записей до и после нее. В приложении C ++ нижняя строка ведет себя аналогично, но здесь она остается неизменной.

Может ли это быть связано с отсутствием указания и разыменования? Или я лаю совсем не на том дереве? Я сделал что-то еще, что явно глупо? Самое главное: как мне заставить это работать?


Обновление: Конструкции и внешние элементы

C ++

// Bird reading structure
typedef struct tagBIRDREADING
{
    BIRDPOSITION    position;   // position of receiver
    BIRDANGLES      angles;     // orientation of receiver, as angles
    BIRDMATRIX      matrix;     // orientation of receiver, as matrix
    BIRDQUATERNION  quaternion; // orientation of receiver, as quaternion
    WORD            wButtons;   // button states
}
BIRDREADING;

// Bird frame structure
//
// NOTE: In stand-alone mode, the bird reading is stored in reading[0], and
//  all other array elements are unused.  In master/slave mode, the "reading"
//  array is indexed by bird number - for example, bird #1 is at reading[1],
//  bird #2 is at reading[2], etc., and reading[0] is unused.
typedef struct tagBIRDFRAME
{
    DWORD           dwTime;     // time at which readings were taken, in msecs
    BIRDREADING     reading[BIRD_MAX_DEVICE_NUM + 1];  // reading from each bird
}
BIRDFRAME;

BOOL DLLEXPORT birdGetMostRecentFrame(int nGroupID, BIRDFRAME *pframe);

C #:

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct BIRDREADING
{
        public BIRDPOSITION position;
        public BIRDANGLES angles;
        public BIRDMATRIX matrix;
        public BIRDQUATERNION quaternion;
        public ushort wButtons;
}

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct BIRDFRAME
{
        public uint dwTime;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 127)]
        public BIRDREADING[] readings;
}

[DllImport(@"Bird.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool birdGetMostRecentFrame(int nGroupID, ref BIRDFRAME frame);

** Обновление 2: Больше структур: **

C ++

#pragma pack(1) // pack the following structures on one-byte boundaries

// Bird position structure
typedef struct tagBIRDPOSITION
{
    short   nX;         // x-coordinate
    short   nY;         // y-coordinate
    short   nZ;         // z-coordinate
}
BIRDPOSITION;

// Bird angles structure
typedef struct tagBIRDANGLES
{
    short   nAzimuth;   // azimuth angle
    short   nElevation; // elevation angle
    short   nRoll;      // roll angle
}
BIRDANGLES;

// Bird matrix structure
typedef struct tagBIRDMATRIX
{
    short   n[3][3];    // array of matrix elements
}
BIRDMATRIX;

// Bird quaternion structure
typedef struct tagBIRDQUATERNION
{
    short   nQ0;        // q0
    short   nQ1;        // q1
    short   nQ2;        // q2
    short   nQ3;        // q3
}
BIRDQUATERNION;

#pragma pack()  // resume normal packing of structures

C #

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDPOSITION
{
    public short nX;
    public short nY;
    public short nZ;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDANGLES
{
    public short nAzimuth;  // azimuth angle
    public short nElevation;    // elevation angle
    public short nRoll;     // roll angle
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct BIRDMATRIX
{
    public fixed short n[9];
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDQUATERNION
{
    public short nQ0;       // q0
    public short nQ1;       // q1
    public short nQ2;       // q2
    public short nQ3;       // q3
}

Ответы [ 4 ]

1 голос
/ 21 апреля 2011

Я попробовал вашу структуру в двух проектах (C ++ / C #), и, похоже, она работает правильно.

Я использую это в C ++:

#include "stdafx.h"
#include "windows.h"

#pragma pack(1) // pack the following structures on one-byte boundaries

// Bird position structure
typedef struct tagBIRDPOSITION
{
    short   nX;         // x-coordinate
    short   nY;         // y-coordinate
    short   nZ;         // z-coordinate
}
BIRDPOSITION;

// Bird angles structure
typedef struct tagBIRDANGLES
{
    short   nAzimuth;   // azimuth angle
    short   nElevation; // elevation angle
    short   nRoll;      // roll angle
}
BIRDANGLES;

// Bird matrix structure
typedef struct tagBIRDMATRIX
{
    short   n[3][3];    // array of matrix elements
}
BIRDMATRIX;

// Bird quaternion structure
typedef struct tagBIRDQUATERNION
{
    short   nQ0;        // q0
    short   nQ1;        // q1
    short   nQ2;        // q2
    short   nQ3;        // q3
}
BIRDQUATERNION;

#pragma pack()  // resume normal packing of structures

typedef struct tagBIRDREADING
{
    BIRDPOSITION    position;   // position of receiver
    BIRDANGLES      angles;     // orientation of receiver, as angles
    BIRDMATRIX      matrix;     // orientation of receiver, as matrix
    BIRDQUATERNION  quaternion; // orientation of receiver, as quaternion
    WORD            wButtons;   // button states
}
BIRDREADING;

#define BIRD_MAX_DEVICE_NUM 126

// Bird frame structure
//
// NOTE: In stand-alone mode, the bird reading is stored in reading[0], and
//  all other array elements are unused.  In master/slave mode, the "reading"
//  array is indexed by bird number - for example, bird #1 is at reading[1],
//  bird #2 is at reading[2], etc., and reading[0] is unused.
typedef struct tagBIRDFRAME
{
    DWORD           dwTime;     // time at which readings were taken, in msecs
    BIRDREADING     reading[BIRD_MAX_DEVICE_NUM + 1];  // reading from each bird
}
BIRDFRAME;

extern "C" __declspec( dllexport ) BOOL birdGetMostRecentFrame(int nGroupID, BIRDFRAME *pframe) {

    pframe->dwTime = GetTickCount();
    for (int i = 0; i < sizeof(pframe->reading)/sizeof(*pframe->reading); i++) {
        pframe->reading[i] = BIRDREADING();
        pframe->reading[i].position.nX = (short)i;
        pframe->reading[i].position.nY = (short)i + 1;
        pframe->reading[i].position.nZ = (short)i + 2;
    }
    return TRUE;
}

И это в C #:

   [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDPOSITION
{
    public short nX;
    public short nY;
    public short nZ;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDANGLES
{
    public short nAzimuth;  // azimuth angle
    public short nElevation;    // elevation angle
    public short nRoll;     // roll angle
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct BIRDMATRIX
{
    public fixed short n[9];
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BIRDQUATERNION
{
    public short nQ0;       // q0
    public short nQ1;       // q1
    public short nQ2;       // q2
    public short nQ3;       // q3
}

    [StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct BIRDREADING
{
        public BIRDPOSITION position;
        public BIRDANGLES angles;
        public BIRDMATRIX matrix;
        public BIRDQUATERNION quaternion;
        public ushort wButtons;
}

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct BIRDFRAME
{
        public uint dwTime;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 127)]
        public BIRDREADING[] readings;
}

    public partial class Form1 : Form
    {
        [DllImport(@"Bird.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool birdGetMostRecentFrame(int nGroupID, ref BIRDFRAME frame);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BIRDFRAME bf = new BIRDFRAME();

            if (checkBox1.Checked)
            {                
                bf.readings = new BIRDREADING[127];
            }

            if (birdGetMostRecentFrame(0, ref bf)) {
                listBox1.Items.Add(bf.dwTime.ToString());
                Console.WriteLine(bf.dwTime.ToString());
                for (int k = 1; k <= 3; k++)
                {
                    var reading = bf.readings[k];
                    Console.WriteLine(String.Format("  [{0}][{1}][{2}]", reading.position.nX.ToString(), reading.position.nY.ToString(), reading.position.nZ.ToString()));
                    listBox1.Items.Add(String.Format("  [{0}][{1}][{2}]", reading.position.nX.ToString(), reading.position.nY.ToString(), reading.position.nZ.ToString()));
                }
            }
        }
    }

В обоих случаях (чтение инициализировано как новое в C # или нет, оно возвращает значимые данные:

40067905
  [1][2][3]
  [2][3][4]
  [3][4][5]
40068653
  [1][2][3]
  [2][3][4]
  [3][4][5]
40069418
  [1][2][3]
  [2][3][4]
  [3][4][5]
40072585
  [1][2][3]
  [2][3][4]
  [3][4][5]

Сделал это на Windows7 64 бит. Я прилагаю ZIP с обоими проектами для VS2010.

Вот ссылка:

http://hotfile.com/dl/115296617/9644496/testCS.zip.html

Похоже, что вы устанавливаете неправильные значения в этой структуре позиции: /

0 голосов
/ 15 апреля 2011

Массивы в .NET основаны на нуле, а не на основе.Может ли это быть?Конечно, .NET также имеет строгую проверку границ, поэтому я ожидал бы, что ваш «последний» доступ к массиву тоже будет с ошибкой.

Без доступа к источнику FlockOfBirds, я не уверен, чтоеще сказать вам.

0 голосов
/ 21 апреля 2011

Просто мысль: вам действительно нужен ref при переходе к вашему методу?

FlockOfBirds.BIRDFRAME frame = new FlockOfBirds.BIRDFRAME();
FlockOfBirds.birdGetMostRecentFrame(1, ref frame);

Если я не ошибаюсь, тогда в c # все классы все равно передаются по ссылке.Возможно, я злюсь, но разве вы не передаете реф в реф?

0 голосов
/ 15 апреля 2011

Кажется, что sysconf.byNumDevices == 1, поэтому i <= sysconf.byNumDevices зацикливается только один раз, и вы читаете неинициализированные сегменты памяти.

Попробуйте распечатать sysconf.byNumDevices, а если оно равно 1, попытайтесь отследить эту проблему.

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