Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.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# PinVokeStack异常的解决方案(从C调用非托管C+;+;dll)-VS2010_C#_Windows_Dll_Pinvoke_Dllimport - Fatal编程技术网

C# PinVokeStack异常的解决方案(从C调用非托管C+;+;dll)-VS2010

C# PinVokeStack异常的解决方案(从C调用非托管C+;+;dll)-VS2010,c#,windows,dll,pinvoke,dllimport,C#,Windows,Dll,Pinvoke,Dllimport,我花了一天的时间来解决这个问题,我不希望其他人也这么做。问题和解决方案如下: 问题:当你试图在C++代码中使用C++的DLL方法时,你会遇到PvIOKESTACKEXIT异常。下面是您在示例中看到的典型声明 不起作用的示例 (C++ .h file) extern "C" { __declspec(dllexport) int Addints(int a, int b); } (C++ .cpp file) extern int Addints(int a, int b) {

我花了一天的时间来解决这个问题,我不希望其他人也这么做。问题和解决方案如下:

问题:当你试图在C++代码中使用C++的DLL方法时,你会遇到PvIOKESTACKEXIT异常。下面是您在示例中看到的典型声明

不起作用的示例

(C++ .h file)
extern "C" {
    __declspec(dllexport) int Addints(int a, int b);
    }

(C++ .cpp file)
extern int Addints(int a, int b) {
        return a+b;
    }

(C# .cs file)
[DllImport("testdll.dll")]
        static extern int Addints(int a, int b);

 static void Main(string[] args)
        {
            Console.WriteLine("Hello world lets add some stuff");
            Int32 a = 3;
            Int32 b = 5;

            Console.WriteLine(Addints(a,b));
        }
当你运行这个程序时,它会抱怨你已经平衡了堆栈(在NOE上!),并且你真的不应该继续。它还说,您应该检查方法的签名,以确保它们匹配

谎言都是谎言

修复:您需要做的是在DLLImport语句中添加一个~小东西,如下所示:

这是修复方法

[DllImport("testdll.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern int Addints(int a, int b);
是的,那个叫会议的事?真的很重要

其他一些提示:
-确保为同一目标构建dll和C#exe。Win32和x86(例如)分别
-确保dll是使用/clr选项(项目属性-配置属性-常规)构建的
-请记住,C++的INT、String、String可能在边界的另一侧不相同(检查以查看类型是如何匹配的) -要获得一个真正好的分步示例,请查看程序snotebook.wordpress.com/2010/01/18/calling-a-cpp-dll-from-cs

简短版本:

确保C#中的DllImport语句包含设置为CallingConvention.Cdecl的CallingConvention参数

有关更多详细信息,请参见上文

我不想这么做,但你的答案不是全部。默认情况下,C/C++使用Cdecl调用约定,因此您必须修改的原因很明显

实际的解决方案只需在C++代码中声明调用约定。< /P>

还有其他调用约定,因此您的答案实际上取决于C/C++非托管代码的调用约定

我怀疑VS2008的原因更多地与.NETFramework3.5有关,而不是其他任何东西

只需将您的函数更改为:

__declspec(dllexport) int __stdcall Addints(int a, int b); 

是的,很可爱。不过,它也能起作用——仔细阅读我写的内容,我说这是对“示例中给出的典型声明”的修正。你可能会问什么样的例子?这里有几个:

dotnetperls.com/dllimport
程序员snotebook.wordpress.com/2010/01/18/calling-a-cpp-dll-from-cs/
blogs.msdn.com/b/jonathanswift/archive/2006/10/02/780637.aspx
msdn.microsoft.com/en-us/library/aa984739(VS.71).aspx
msdn.microsoft.com/en-us/library/26thfadc.aspx
www.codeguru.com/columns/kate/article.php/c3947
www.apachetechnology.net/KC/NativeDLL2Net.aspx

到目前为止,我还没有看到这种变体。然而,如果它们都能起作用,那么问题在哪里呢?如果你需要荣誉,那就来吧:好极了!荣誉现在人们有两种选择。哦,顺便说一句,你的“答案不是全部答案”:

您还需要更改cpp文件


再一次-我使用.Net 4访问VS2010(不确定您在评论VS2008时指的是什么)。

很抱歉,前面的平台调用数据类型链接已断开,请参见:


您应该能够在Windows上使用默认的呼叫约定,如果无法使用,则说明存在其他问题。我当然可以导入非托管库,而无需声明调用约定。您应该做的是将此作为一个问题,然后提供“修复”部分作为下面的答案。这是一个问答网站,不是论坛。请看,我应该添加我用来定义8、16、32和64有符号和无符号数字的库。NET恰好定义了相同的类型。你好,第一个帖子巨魔。。。Ramhound,我的配置是VS2010,XP上的.NET4。我的设置没有问题。SwDevMan81,天哪,如果你等一会儿而不是跳到我身上,你会看到我这么做:P和拉米?是的,我都试过了,但你还是没有领会我文章的要点。只是想帮助别人,如果你不喜欢的话,很抱歉。我有完全相同的设置,我的非托管库可以通过声明调用约定导入,你的解决方案不是全部答案。继续给人们“提示”但是忽略了您应该简单地匹配C/C++非托管代码的调用约定的部分。我很清楚您使用的是Visual 2010,我也在使用它,与您列出的设置完全相同。我关于VisualStudio2008(.NETFramework 3.5)的声明与代码正常工作的原因有关。
 (C++ .h) extern "C" {
     __declspec(dllexport) int __stdcall Addints(int a, int b);  }


 (C++ .cpp) int __stdcall Addints(int a, int b) {
 return a+b; }