views:

355

answers:

3

Hi there I have a regular dll with the followign fucntion exported.

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

LocationStruct is very simple

struct LocationStruct
  {
   long positionIndex;
   long item;
  };

I'm tryign to call it from c# using

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

Its all cool and funky and i can step into the dll function from the debugger. Inside the dll the LocationStruct array is populated correctly and all is very good.

the problem i have is when it returns back from the dll, the LocationStruct array is not coming back with the data - just empty values...

what am i missing?

cheers

Buzz

A: 

I'm not sure that you will be able to do this automatically since C# has no way of knowing how many items are returned in the locations variable (I'm assuming that the return value of FindNearestStuff is the number of entries in locations.)

You will have to manually marshal your data using the Marshall class and a process like this:

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

I haven't actually tried this so caveat emptor.

shf301
+1  A: 

Hi Chaps

thanks so much for your help - you certainly put me onthe right direction and i really appreciate your assistance!

This is the solution which seems to work for me;

[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;
        }
buzz
and of course dont forget to Marshal.FreeHGlobal(buffer);!
buzz
If that works for you, you indeed had one level of indirection too much in your original code, just like Pavel hinted. You don't have to do all this allocation and copying yourself, you should be able to take your original function declaration and just remove the ref modifier on the array parameter.
Mattias S
A: 

* THANK YOU *

All my experience in C++, and I tried to forget it all for C#. But knowing where pointers are pointing to is essential!

Thanks again

James