передача массива структур из c # в обычную dll - PullRequest
1 голос
/ 19 ноября 2009

У меня есть обычная dll со следующей экспортированной функцией.

extern "C" __declspec(dllexport) int FindNearestStuff(double _latitude, double _longitude , LocationStruct * locations[])

LocationStruct очень прост

struct LocationStruct
  {
   long positionIndex;
   long item;
  };

Я пытаюсь позвонить с c #, используя

 [DllImport("myclever.dll", CharSet = CharSet.None)]
        private static extern int FindNearestStuff(double _latitude, double _longitude, 
                                                    ref LocationStruct [] locations);

Это все круто и забавно, и я могу войти в функцию dll из отладчика. Внутри dll массив LocationStruct заполнен правильно, и все очень хорошо.

У меня проблема в том, что когда он возвращается из библиотеки dll, массив LocationStruct не возвращается с данными - просто пустые значения ...

Чего мне не хватает?

Ответы [ 2 ]

1 голос
/ 19 ноября 2009

Большое спасибо за вашу помощь - вы, безусловно, направили меня в правильном направлении, и я очень ценю вашу помощь!

Это решение, которое мне подходит;

[DllImport("myclever.dll", CharSet = CharSet.None)]
        private static extern int FindNearestStuff(double _latitude, double _longitude,  IntPtr locations);


public static int FindNearestStuff(double _latitude, double _longitude, LocationStruct[] locations)
        {
            int returnValue = -1;
            LocationStruct temp;
            temp.roadIndex = 1;
            temp.tdist = 1;
            int iStructSize = Marshal.SizeOf(temp);
            try
            {
                IntPtr locationsPtr = IntPtr.Zero;

                IntPtr buffer = Marshal.AllocHGlobal(iStructSize * 10);
                FindNearestRoads(_latitude, _longitude,  buffer);
                for (int i = 0; i < 10; i++)
                {
                    IntPtr ptr = new IntPtr(buffer.ToInt32() + iStructSize * i);
                    locations[i] = (LocationStruct)Marshal.PtrToStructure(ptr, typeof(LocationStruct));

                }

                returnValue = 0;
            }
            catch
            {
            }
            return returnValue;
        }
0 голосов
/ 19 ноября 2009

Я не уверен, что вы сможете сделать это автоматически, поскольку C # не может узнать, сколько элементов возвращено в переменной location (я предполагаю, что возвращаемое значение FindNearestStuff - это количество записей в местах.)

Вам придется вручную упорядочить ваши данные, используя класс Marshall и такой процесс:

[DllImport("myclever.dll", CharSet = CharSet.None)]
private static extern int FindNearestStuff(double _latitude, double _longitude, 
                                           out IntPtr locations);

public static LocationStruct[] FindNearestStuff(double latitude, double longitude) {
    IntPtr locationsPtr = IntPtr.Zero;
    int numLocations = FindNearestStuff(latitude, longitude, out locationsPtr);

    LocationsStruct[] locations = new LocationsStruct[numLocations];

    for (int i = 0; i < numLocations; i++) {

          // locationsPtr is a pointer to the struct, so read the value
          // at locationPtr which will be the address of the struct and
          // then manually marshal the struct from that address
          locaitonsStruct[i] = (LocationStruct)Marshal.PtrToStructure(
              Marshal.ReadIntPtr(locationsPtr), typeof(LocationsStruct));

          // Move to the location pointer to the next address of a 
          // pointer to a struct
          locationsPtr += IntPtr.Size;  
    }

    return locations;
}

Я на самом деле не пробовал, так что будьте бдительны.

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