Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.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/8/sorting/2.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# 从托管代码调用非托管DLL函数时出错 我在非托管VisualC++中编写了一个DLL,并且在使用C和C++应用程序时遇到了一些麻烦。下面是C++ DLL中原型的例子: extern "C" __declspec(dllexport) int WINAPI ZBNConnect( UCHAR dev, LPARAM hWnd, ZBCallbackFn rfn, ZBCallbackFn nfn, int DevType, byte * DevAddr, ZBCallbackFn dfn );_C#_C++_Dll - Fatal编程技术网

C# 从托管代码调用非托管DLL函数时出错 我在非托管VisualC++中编写了一个DLL,并且在使用C和C++应用程序时遇到了一些麻烦。下面是C++ DLL中原型的例子: extern "C" __declspec(dllexport) int WINAPI ZBNConnect( UCHAR dev, LPARAM hWnd, ZBCallbackFn rfn, ZBCallbackFn nfn, int DevType, byte * DevAddr, ZBCallbackFn dfn );

C# 从托管代码调用非托管DLL函数时出错 我在非托管VisualC++中编写了一个DLL,并且在使用C和C++应用程序时遇到了一些麻烦。下面是C++ DLL中原型的例子: extern "C" __declspec(dllexport) int WINAPI ZBNConnect( UCHAR dev, LPARAM hWnd, ZBCallbackFn rfn, ZBCallbackFn nfn, int DevType, byte * DevAddr, ZBCallbackFn dfn );,c#,c++,dll,C#,C++,Dll,我的C#应用程序可以链接到函数,没有问题,但当它尝试调用函数时,会引发异常: catch (Exception e) { /* ... */ } e、 Message=“对象引用未设置为对象的实例。” 奇怪的是,如果我从DLL中的原型中取出WINAPI,然后重新编译,C#应用程序调用该函数时不会出现任何问题。不幸的是, WiAPI > /COD>必须保留,因为这是C++中定义函数的方式。 该函数目前在C#应用程序中的原型如下: public delegate int ZBNConnectDel

我的C#应用程序可以链接到函数,没有问题,但当它尝试调用函数时,会引发异常:

catch (Exception e) { /* ... */ }
e、 Message=“对象引用未设置为对象的实例。”

奇怪的是,如果我从DLL中的原型中取出
WINAPI
,然后重新编译,C#应用程序调用该函数时不会出现任何问题。不幸的是, WiAPI > /COD>必须保留,因为这是C++中定义函数的方式。 该函数目前在C#应用程序中的原型如下:

public delegate int ZBNConnectDelegate(uint dev, IntPtr hWnd, USBCallbackDelegate rfn, NotifyCallbackDelegate nfn, uint DevType, byte[] DevAddr, ZBdebugCallbackDelegate dfn);
public ZBNConnectDelegate ZBNConnect;

procName = "ZBNConnect";
fUintPtr = Kernel32.GetProcAddress(dllHandle, procName);

if (fUintPtr == UIntPtr.Zero)
{
    throw new ArgumentException(procName);
}

fIntPtr = unchecked((IntPtr)(long)(ulong)fUintPtr);
ZBNConnect = (ZBNConnectDelegate)Marshal.GetDelegateForFunctionPointer(fIntPtr, typeof(ZBNConnectDelegate));
如何修改C#应用程序以使其正常工作?谢谢

编辑:附加信息


静态链接(
[DllImport…]
)不是选项,因为根据连接到系统的硬件,在运行时会加载支持连接硬件的不同DLL。两个DLL都有相同的API调用。

基本上出了问题。您声明了一个委托,就好像函数是回调一样。看起来一点也不像回调,它看起来像是你应该用[DllImport]声明的东西。要使其像以前一样工作,必须使用pinvoke LoadLibrary和GetProcAddress()。[DllImport]在引擎盖下做什么。我看不到您在使用它。

WINAPI宏更改了调用约定

试一试

extern“C”uu declspec(dllexport)intwinapi zbnconconnect(UCHAR dev、LPARAM hWnd、ZBCallbackFn rfn、ZBCallbackFn nfn、intdevtype、byte*devddr、ZBCallbackFn dfn)

public委托int-ZBNConnectDelegate(uint-dev、IntPtr-hWnd、USBCallbackDelegate-rfn、NotifyCallbackDelegate-nfn、uint-DevType、byte[]DevAddr、zbdugcallbackdelegate-dfn)


C++UCHARs(dev)是1字节值,C#uint是4字节值。当您进行本机调用时,您正在破坏堆栈,并且出于某种原因,WINAPI让您得以逃脱。此外,像这样使用委托而不是执行普通的P/Invoke dlliport很可能会给您带来问题,因为您无法自定义封送方式。

如果您可以在运行时从C端检测到正确的DLL,我将使用两个dlliport声明:

[DllImport("Dll1.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ZBNConnect")]
extern static int ZBNConnect1(...)
[DllImport("Dll2.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ZBNConnect")]
extern static int ZBNConnect2(...)

public static int ZBNConnect(...)
{
    if (UseDll1)
        return ZBNConnect1(...);
   return ZBNConnect2(...);
}
注意

p/Invoke是通过动态加载传递的。如果从未调用ZBNConnect1,则从未加载Dll1.dll,反之亦然

已更新


将EntryPoint=添加到DllImport。

结果表明,将
WINAPI
添加到函数声明和定义中会导致DLL中的函数名损坏。不幸的是,
WINAPI
是维护与已经部署的应用程序的兼容性所必需的。修复方法是向链接器添加额外的导出:

#pragma comment(linker, "/EXPORT:ZBNConnect=_ZBNConnect@28")

这不是完全不同的DLL地狱您是否尝试将extern放入原型中?那么,如何初始化
ZBNConnect
,并使其指向非托管函数?如前所述,它将是
null
。为什么不直接使用P/Invoke(
[DllImport]static extern
)?好的,那么实际上使用的是GetProcAddress。嗯,非托管代码在空指针上急剧下降。有大量的候选者,函数参数都是指针。你必须调试它。我想您已经知道如何调试非托管代码了,对吧?我还没有尝试进入DLL,但是当我逐步通过托管代码时,
fIntPtr
ZBNConnect
都是赋值(非空)。您不能进入非托管代码,您必须在函数上设置断点。小于机器字的传递值参数放在堆栈上时会变宽。嗯,我不确定您是否100%保证能够成功,尽管这确实解释了WINAPI工作的原因。说得好。
#pragma comment(linker, "/EXPORT:ZBNConnect=_ZBNConnect@28")