Hi Folks,

This quandary should be fairly straight forward but I have yet to find an example that works. Essentially I have a struct, I create an array of these structs in C#, pass the array to C++, do some manipulation on the C++ side and return the results to C#. Everything works fine until I try to pass the data back.

My DLL import looks like this

[DllImport(DLL_LOC, EntryPoint = "_request_advanced_search@76")]
private static extern void request_advanced_search(
  ref Int32 iDataSize, 
  ref TrackRecord [] recordBlock, 
  AdvancedSearch searchCriteria);

And the function on the C++ side looks like this

FUNCTION void __stdcall request_advanced_search(int & iDataSize,TrackRecord *recordBlock[],AdvancedSearch searchCriteria)
{
  TrackRecord * passedRecords = new TrackRecord[iDataSize];
  passedRecords = *recordBlock;

  AdvancedFilters * advFilt = new FilterByDate(...);
  advFilt->run_filter(&searchCriteria,passedRecords,iDataSize); 
}

What I want to do is return the records that satisfy some search criteria. Since I know the number of results in my query I've tried using an IntPtr and traversing what I thought should be the resultant array. Since I'm passing by reference I've tried to reassign the passed array with the search results, but that too fails. I've tried returning the array but I get the error "Cannot marshal 'return value': Invalid managed/unmanaged type combination".

Can anyone provide some insight/code to help solve this problem?

Thanks in advance,

Scott

Most likely your problem is the reference to the TrackRecord array. C# has no way of knowing how big it is when it is returned from the C++ code (since you are passing it as a reference) so it fails.

One way to fix this is to pass it a reference to a pre-allocated array, and ensure that the C++ code doesn't exceed the size of the array.

Also, without knowing what the C++ definition for the various structures you are using it's impossible to tell if your P/Invoke call/format is correct.

Most likely your problem is the reference to the TrackRecord array. C# has no way of knowing how big it is when it is returned from the C++ code (since you are passing it as a reference) so it fails.

One way to fix this is to pass it a reference to a pre-allocated array, and ensure that the C++ code doesn't exceed the size of the array.

Also, without knowing what the C++ definition for the various structures you are using it's impossible to tell if your P/Invoke call/format is correct.

Originally my idea was since I've got the number of records returned I could do as I did on the C++ side and create a new array of the passed size and point the new array at the referenced one. For example (in C++)

FUNCTION TrackRecord * __stdcall request_advanced_search(int & iDataSize,TrackRecord *recordBlock[],AdvancedSearch searchCriteria)
{
  passedRecords = new TrackRecord[iDataSize];
  passedRecords = *recordBlock;
...

The struct is rather unwieldy so let's just say it looks like the following:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
  public struct GenericNumberType<T>
  {
    public Int32 hasValue;
    public T value;
  }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct TrackRecord
    {
      public Int32 Index, Year, Month, Day, Hour, Minute, Second;
      public GenericTrackRecord<Int32> Motion;
      public Coordinates Coordinates;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct Coordinates
    {
      public double Altitude;
      public double Longitude;
      public double Latitude;
      [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 255)]
      public string Str;
    }

(My struct is as I describe it above, just some more doubles and strings) And on the C++ side I have the corresponding struct definition.

This article has been dead for over six months. Start a new discussion instead.