Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.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++;回拨_C#_C++_Delegates_Callback_Dllimport - Fatal编程技术网

C#代表C++;回拨

C#代表C++;回拨,c#,c++,delegates,callback,dllimport,C#,C++,Delegates,Callback,Dllimport,我想我基本上理解了如何为回调编写c#委托,但这一点让我感到困惑。 C++定义如下: typedef int (__stdcall* Callback)( long lCode, long lParamSize, void* pParam ); 我的c#方法是: unsafe delegate int CallbackDelegate (int lCode, int lParamSize, IntPtr pParam); 虽然这似乎不正确,因为我得到了一个PInvokeStackInbal

我想我基本上理解了如何为回调编写c#委托,但这一点让我感到困惑。 C++定义如下:

typedef int (__stdcall* Callback)(
long lCode,
long lParamSize,
void* pParam 
);
我的c#方法是:

 unsafe delegate int CallbackDelegate (int lCode, int lParamSize, IntPtr pParam);
虽然这似乎不正确,因为我得到了一个PInvokeStackInbalance错误,这意味着我对委托的定义是错误的

函数的其余参数是字符串或int,这意味着它们不会导致错误,如果我只传递一个IntPtr.Zero而不是委托(这意味着我指向的是一个不存在的回调函数),我会得到一个accessinvalition错误,这也是有意义的

我做错了什么

编辑:

P>完全C++函数为:

int
__stdcall
_Initialize (
const char*         FileName,
Callback            cbFunction,
int                 Code,
const char*         Name,
unsigned int        Option,
unsigned int        Option2
);
我的c版本是:

[DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int _Initialize (string FileName, CallbackDelegate cbFunction, int Code, string Name, uint Options, uint Options2);
该函数(用于测试)仅在控制台应用程序的主例程中调用:

static void Main(string[] args)
{
    CallbackDelegate del = new CallbackDelegate(onCallback);

    Console.Write(_Initialize("SomeFile.dat", del, 1000, "", 0, 4));
    Console.Read();
}
其中
onCallback
是:

static int onCallback(int lCode, int lParamSize, IntPtr pParam)
{
    return 0;
}

如果我传递的是
IntPtr.Zero
,而不是委托,我在调用
\u Initialize
的行中得到
PInvokeStackInbalance
错误,将函数的定义改为
IntPtr
而不是
CallbackDelegate
,然后我得到一个
AccessViolationException
a.NET
long
是64位。一个C++ <代码>长< /> >可能只有32位。用C++编译器检查它的定义,它的大小是“代码>长< /Calp>s”。
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
unsafe delegate int CallbackDelegate (int lCode, int lParamSize, IntPtr pParam);

如果.NET采用cdecl而不是stdcall,那么您的堆栈肯定会被处理。

我将您的代码添加到当前的项目中,我在VS2012中进行了大量的C#/C++互操作。虽然我讨厌使用“它在我的机器上工作”,但它对我来说很好。下面列出了我运行时的代码,只是为了说明我没有做任何根本性的更改

我的建议是,您使用一个存根函数为_Initialize构建一个新的本机dll,如下所示,并在您可以控制接口的两侧时查看它是否工作。如果这可以工作,但实际的dll不能工作,那么这就归结为本机端的编译器设置,或者本机端的编译器设置是一个bug,并且会在堆栈上跺脚

extern "C" {

    typedef int (__stdcall* Callback)(long lCode,long lParamSize,void* pParam );

    TRADITIONALDLL_API int __stdcall _Initialize (const char* FileName,Callback cbFunction, int                 Code,
                                const char*         Name,unsigned int        Option,unsigned int        Option2)
    {
        cbFunction(0, 0, nullptr);
        return 0;
    }
}
在C#端,我将声明添加到接口类中:

 public delegate int CallbackDelegate(int lCode, int lParamSize, IntPtr pParam);

 [DllImport("XXX.dll", CallingConvention = CallingConvention.StdCall)]
 public static extern int _Initialize(string FileName, CallbackDelegate cbFunction, int Code, string Name, uint Options, uint Options2);
然后在我的主要发言中:

private int onCallback(int lCode, int lParamSize, IntPtr pParam)
{
       return 0;
}
XXXInterface.CallbackDelegate del = new XXXInterface.CallbackDelegate(onCallback);

Console.Write(XXXInterface._Initialize("SomeFile.dat", del, 1000, "", 0, 4));

很好的输入,遗憾的是,这似乎无法解决问题。我不能检查C++编译器,因为我只有.dll和.h文件,但是更改长到int 32没有帮助。<代码>函数的其余参数是字符串或int 。不要隐藏信息。您是否尝试过不使用不安全的?i、 e:委托int CallbackDelegate(int lCode、int lParamSize、IntPtr pParam)@我不是在试图隐藏信息,我是在试图抛开我认为不相关的东西。我将编辑问题并添加信息。@DougEC现在只是尝试了一下,似乎并没有帮助解决您的问题,因为您的代码已更改,以反映给您的建议。IntPtr而不是void*和ints而不是long。还包括调用函数的方式以及在什么时候出现异常。您使用的是32位还是64位系统?谢谢您的检查,我应该自己做的。我也试过了,似乎很管用。我们还发现,如果我只是启动exe文件,而没有调试器,应用程序似乎可以工作……这很奇怪。这听起来像是一个很好的机会,在一个错误的C++侧DLL,影响堆栈。有没有办法获取本机dll的源代码,以便在调试器下组合运行它们?我不知道还有什么好的方法来处理它,而且几乎肯定没有办法用源代码来修复它。不,很遗憾,我无法获得源代码,否则我认为这会容易得多。我试着从C++程序调用C++函数,这看起来很好。因此,我认为dll是正确的,我只是在回调函数上犯了一个错误。谢谢你的帮助。