C# C DllIimport非托管C代码应用程序(exe)文件引发AccessViolationException异常
我目前正致力于导出Win32应用程序的一些函数,以便从托管代码中调用它,而AccessViolationException则让我陷入困境。它是一个非常简单的DllImport,具有简单的类型,但只要我在非托管应用程序中调用malloc或printf之类的函数,它就会抛出异常 下面是一个代码示例: //C程序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
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运行时没有初始化。