将结构数组从c#传递给常规dll

时间:2009-11-19 02:54:07

标签: c# arrays data-structures

我有一个常规的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 个答案:

答案 0 :(得分:1)

非常感谢你的帮助 - 你当然让我走上了正确的方向,我非常感谢你的帮助!

这个解决方案似乎对我有用;

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

答案 1 :(得分:0)

我不确定你是否能够自动执行此操作,因为C#无法知道locations变量中返回了多少项(我假设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;
}

我实际上并没有尝试过这样的警告。