C#DllIimport非托管C代码应用程序(exe)文件抛出AccessViolationException

时间:2013-06-27 13:18:47

标签: c# marshalling dllimport unmanaged

我目前正在尝试导出Win32应用程序的一些函数,以便从托管代码中调用它,我陷入了AccessViolationException。这是一个非常简单的DllImport,只有简单的类型,但只要在非托管应用程序中调用malloc或printf之类的函数,就会抛出异常。

以下是代码示例: // C#Program

static void Main(string[] args)
{
  uint result = MyClass.ExecuteCommand((byte)10);
  Console.WriteLine(result);
  Console.ReadLine();
}

// C#类库

public const string AppicationExe= "Application.exe";

[DllImport(AppicationExe, EntryPoint = "ExecuteCommand")]
public static extern UInt32 ExecuteCommand(byte mybyte);

// C Application

__declspec(dllexport) UINT32 __stdcall ExecuteCommand(unsigned char mybyte)
{ 
  printf("Why is it so difficult to make it works !!!!!!");
  return 0;
}

1 个答案:

答案 0 :(得分:3)

托管 DLL与EXE之间的非常差别不大。您可以将类库的程序集重命名为* .exe,程序仍然有效。

然而,对于C程序来说,不是的情况。 EXE与DLL有很大不同。首先,C程序要求始终在main()函数中启动代码。需求是因为在C程序开始运行之前,必须首先初始化C运行时库。必须在开始执行托管代码之前初始化CLR的粗略等价物。像你一样跳过初始化很可能在程序使用C运行时函数时崩溃。喜欢printf()。

完全不是托管代码中的问题,因为CLR在执行程序之前总是先被初始化。

另一个非常重要的细节是,非托管EXE通常由链接器优化,尽管它们正在消失。可执行文件通常具有重定位表,当程序加载到与其请求的基址不同的地址时,需要调整的地址列表。始终需要DLL,因为加载地址不可预测,地址可能已在使用中。 EXE不需要,因为它总是加载到可预测的地址,因此链接器会剥离该表以使文件更小。 Kaboom如果程序实际上 被加载到错误的地址,那么当你进行pinvoke时它总会出现。

由于抖动,托管代码完全没有问题。

您需要创建一个DLL。在Visual Studio中轻松使用项目向导。选择Win32 Project项目模板,然后选择" DLL"下一个向导步骤中“应用程序类型”设置的项目符号。