3

我目前正在导出 Win32 应用程序的一些函数,以便从托管代码中调用它,但我遇到了 AccessViolationException。这是一个非常简单的具有简单类型的 DllImport,但是一旦我在非托管应用程序中调用 malloc 或 printf 之类的函数,它就会引发异常。

这是一个代码示例://C#程序

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 应用程序

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

1 回答 1

4

托管DLL 和 EXE之间几乎没有区别。您可以将类库的程序集重命名为 *.exe,您的程序仍然可以工作。

然而,C 程序并非如此。EXE 与 DLL 有很大不同。一方面,C 程序要求代码始终从 main() 函数开始。一个要求,因为在 C 程序开始运行之前,必须首先初始化 C 运行时库。在开始执行托管代码之前,必须初始化 CLR 的粗略等价物。像您一样跳过初始化很可能在程序使用 C 运行时函数时崩溃。像 printf()。

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

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

由于抖动,托管代码中完全不是问题。

您将需要创建一个 DLL。使用 Visual Studio 中的项目向导轻松完成。选择 Win32 Project 项目模板并在下一个向导步骤中为 Application Type 设置选择“DLL”项目符号。

于 2013-06-27T15:55:50.887 回答