C# DllImport 32位工作,64位失败(AccessViolationException)

C# DllImport 32位工作,64位失败(AccessViolationException),c#,.net,dllimport,mapinfo,C#,.net,Dllimport,Mapinfo,我在C#中使用.Net为MapInfo Pro构建了一个扩展。较早版本的MapInfo是32位应用程序,最新版本是64位应用程序。我想让我的分机和这两个都能用。 虽然可以使用.Net调用MapInfo的许多功能,但其中一些功能仅适用于非托管DLL。 其中一个dll名为migrid.dll,我有32位和64位版本。 但是,我没有源代码,因此无法获得该文件中函数的确切定义 我想使用的函数之一是GE_WriteContinuousValue。 关于该函数,我仅有的文档是如何使用MapBasic(Map

我在C#中使用.Net为MapInfo Pro构建了一个扩展。较早版本的MapInfo是32位应用程序,最新版本是64位应用程序。我想让我的分机和这两个都能用。 虽然可以使用.Net调用MapInfo的许多功能,但其中一些功能仅适用于非托管DLL。 其中一个dll名为migrid.dll,我有32位和64位版本。 但是,我没有源代码,因此无法获得该文件中函数的确切定义

我想使用的函数之一是GE_WriteContinuousValue。 关于该函数,我仅有的文档是如何使用MapBasic(MapInfo的默认编程语言)声明它:

声明函数GE_WriteContinuousValue Lib“Migrid.dll”(

ByVal hGrid为整数,'网格句柄

ByVal lCol为整数,'列号

ByVal lRow为整数,“行数”

ByVal D值作为浮点“z”值

)如果有错误,则为逻辑“FALSE”

“成功才是真的

在我的c#代码中,我将此函数与DllImport一起使用:

[DllImport("migrid.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool GE_WriteContinuousValue(int hGrid, int lCol, int lRow, double dValue);
然后将其称为,例如:

GE_WriteContinuousValue(iGridID, c, r, value);
使用32位dll,它可以正常工作。 当我将其用于64位dll时,我在这一行得到一个“'System.AccessViolationException'尝试读取或写入受保护内存”:

GE_WriteContinuousValue(iGridID, c, r, value);

同一dll中的其他函数对于32位和64位都可以正常工作。所以它必须是这个函数的特定对象

我在网上搜索了一下,找到了一个叫做雪人的工具,希望能找到这个函数的确切定义。这给了我一些信息,但对我没有任何用处。也许对你有帮助

来自32位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;
}
来自64位dll的结果:

void fun_180001b50() {
goto GE_WriteContinuousValue;
}

int64_t GE_WriteContinuousValue = 0x577c;

void GE_WriteContinuousValue() {
goto GE_WriteContinuousValue;
}

有人能帮我摆脱System.AccessViolationException吗?或者给我指出一点正确的方向吗?

我怀疑参数类型的位宽度与p/调用函数的返回类型不匹配。您必须查阅MapBasic文档,以确定在x64构建的上下文中,这些整数、浮点和逻辑类型的位宽度。然后在此处查看P/Invoke声明中使用的封送.NET值类型的位宽度:。比较并选取其编组位宽度与MapBasic类型的x64版本完全对应的.NET值类型。根据进程位的不同,句柄可能为32/64位(即使用
IntPtr
)。您应该阅读随DLL提供的文档以了解。如果没有任何具体的东西,那么没有人能做的比这种推测更多,我们也不能真正写出答案。它不应该是
float-dValue)
?“所以它必须是这个函数的特定内容。”这不是一个给定的答案。对其他函数的其他调用可能会导致此函数无法正常工作,或者在计算偏移量值时出现错误,因为未考虑位差异。这里的帮助是使用使运行时更仔细地查看您正在做的事情。谢谢大家的建议。非常有用的信息@DavidHeffernan你是对的,将int hGrid更改为int ptr hGrid成功了。现在它适用于32位和64位,谢谢!!