Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C DllIimport非托管C代码应用程序(exe)文件引发AccessViolationException异常_C#_Marshalling_Dllimport_Unmanaged - Fatal编程技术网

C# C DllIimport非托管C代码应用程序(exe)文件引发AccessViolationException异常

C# C DllIimport非托管C代码应用程序(exe)文件引发AccessViolationException异常,c#,marshalling,dllimport,unmanaged,C#,Marshalling,Dllimport,Unmanaged,我目前正致力于导出Win32应用程序的一些函数,以便从托管代码中调用它,而AccessViolationException则让我陷入困境。它是一个非常简单的DllImport,具有简单的类型,但只要我在非托管应用程序中调用malloc或printf之类的函数,它就会抛出异常 下面是一个代码示例: //C程序 static void Main(string[] args) { uint result = MyClass.ExecuteCommand((byte)10); Console.W

我目前正致力于导出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;
}
托管DLL和EXE之间几乎没有区别。您可以将类库的程序集重命名为*.exe,并且您的程序仍然可以运行

然而,C程序并非如此。EXE与DLL有很大的不同。首先,C程序要求代码总是从主函数开始。这是一个要求,因为在C程序开始运行之前,必须先初始化C运行时库。大致相当于CLR在开始执行托管代码之前必须进行初始化。与您一样,跳过初始化很可能会使程序在使用C运行时函数时崩溃。像printf

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

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

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


您将需要创建一个DLL。在VisualStudio中使用项目向导很容易。选择Win32 Project项目模板,并在下一个向导步骤中为应用程序类型设置选择DLL项目符号。

我使用/MT编译Application.exe文件,从sysinternalstry调用listDlls.exe以指定CallingConvention=CallingConvention.CdeclApplication.exe时可以找到msvcrt.DLL?为什么不呢?从.exe调用函数并不简单。不支持在exe中调用Pinvoking代码。C运行时未初始化,重新定位也不起作用。谢谢您的回答。您是对的,即使我在应用程序中添加了DllMain,它也不会被调用,正如您所说的,这就是为什么C运行时没有初始化。