2

I have built an extension for MapInfo Pro using .Net in C#. Older versions of MapInfo are 32-bit applications, the newest are 64-bit. I want my extension to work with both. While a lot functionality of MapInfo can be called using .Net, some of them only work with unmanaged dlls. One of those dlls is called migrid.dll, which I have in a 32-bit and a 64-bit version. However I do not have the source code, so I'm not able to get the exact definitions of the functions in that file.

One of the functions I want to use is GE_WriteContinuousValue. The only documentation I have about that function is how to declare it using MapBasic (the default programming language for MapInfo):

Declare Function GE_WriteContinuousValue Lib "Migrid.dll" (

ByVal hGrid As Integer, 'grid handle

ByVal lCol As Integer, 'column number

ByVal lRow As Integer, 'row number

ByVal dValue As Float 'z value

) As Logical 'FALSE if there is an error

'TRUE on success

In my c# code i'm using this function with a DllImport:

[DllImport("migrid.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool GE_WriteContinuousValue(int hGrid, int lCol, int lRow, double dValue);

and then call it for example with:

GE_WriteContinuousValue(iGridID, c, r, value);

Which works fine using the 32-bit dll. When I use the same for the 64-bit dll I get a "'System.AccessViolationException' Attempted to read or write protected memory" at this line:

GE_WriteContinuousValue(iGridID, c, r, value);

Other functions in the same dll work without problems for both 32-bit and 64-bit. So it must be something specific for this function.

Hoping there is a way to get the exact definition of this function I have searched the internet and found a tool called snowman. Which gave me some information, but not anything useful for me. Maybe it helps you?

Result from the 32-bit dll:

struct s43 {
signed char[4] pad4;
int32_t f4;
};

struct s44 {
signed char[4] pad4;
int32_t f4;
};

/* migridu.dll:222 */
int32_t migridu_dll_222 = 0x800000de;

void GE_WriteContinuousValue(int32_t a1, int32_t a2, int32_t a3) {
int32_t* edi4;
int32_t* esi5;
struct s43* edi6;
struct s44* esi7;

*edi4 = *esi5;
edi6->f4 = esi7->f4;
migridu_dll_222();
goto a2;
}

Result from the 64-bit dll:

void fun_180001b50() {
goto GE_WriteContinuousValue;
}

int64_t GE_WriteContinuousValue = 0x577c;

void GE_WriteContinuousValue() {
goto GE_WriteContinuousValue;
}

Can someone help me get rid of the System.AccessViolationException or point me a little bit in the right direction?

Community
  • 1
  • 1
Sander
  • 122
  • 1
  • 8
  • 1
    I suspect a mismatch of the bit-width of the argument types and the return type of the P/Invoked function. You will have to look up the MapBasic documentation to figure out what the bit-widths of those Integer, Float, and Logical types are in the context of a x64 build. Then look here to see the bit-width of the marshalled .NET value types used in your P/Invoke declaration: https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-data-with-platform-invoke. Compare and pick .NET value types whose marshalled bit-width correspond **exactly** to the x64-versions of the MapBasic types. –  Jun 21 '19 at 11:16
  • 2
    Probably the handles are 32/64 bit depending on the process bitness (i.e. use `IntPtr`). You should read the documentation supplied with the DLL to find out. Without anything concrete then nobody can do more than such speculation and we can't really write an answer. – David Heffernan Jun 21 '19 at 11:17
  • Shouldn't it be `float dValue)` ? – Stefan Jun 21 '19 at 11:21
  • 1
    "So it must be something specific for this function." This is not a given. Other calls to other functions may have screwed things up to the point where this one doesn't work correctly, or else something goes wrong in calculating values for offsets because the bitness difference isn't taken into account. What can help here is using the [managed debugging assistants](https://learn.microsoft.com/dotnet/framework/debug-trace-profile/diagnosing-errors-with-managed-debugging-assistants) to make the runtime look more closely at what you're doing. – Jeroen Mostert Jun 21 '19 at 11:22
  • 1
    Thank you all for your suggestions. Really helpful information. @DavidHeffernan you are right, changing int hGrid to IntPtr hGrid did the trick. Now it works for 32-bit and 64-bit, thanks!! – Sander Jun 21 '19 at 13:01
  • Guessing is not productive though. You really need to use the documentation or header file. – David Heffernan Jun 21 '19 at 13:06
  • Yes you are absolutely right, but I was not able to find any more information. So I'm glad you helped me guessing. Is there a way I can give you the credits for solving my issue? – Sander Jun 21 '19 at 13:15

0 Answers0