C#EXE w / Unmanaged C ++ Unicode DLL链接到非托管C ++ ANSI DLL崩溃

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#EXE w / Unmanaged C ++ Unicode DLL链接到非托管C ++ ANSI DLL崩溃相关的知识,希望对你有一定的参考价值。

我有一个C#可执行文件加载到DLL中,这是一个unicode非托管C ++ DLL。这个非托管C ++ DLL也链接到另一个DLL,一个恰好是ANSI的非托管C ++ DLL。

当我运行我的C#可执行文件时,程序最终崩溃在DLL调用的ANSI部分(我还没能拉出异常)。但是,通过简单地将ANSI DLL切换为Unicode,一切都有效,除了有第三个DLL,来自另一家公司的SDK,它对unicode / ANSI有明显的敏感性,所以如果调用DLL它最好是ANSI。

因此,我们在一个非托管unicode C ++ DLL中有一个可执行调用函数,它作为非托管ANSI C ++ DLL的包装器,它是我们没有任何信息的最终非托管DLL的包装器。

将两个中间DLL切换为unicode只会使崩溃与第三个独立的供应商DLL失败(但不会因灾难而失败,只是输出不正确)。我们无法将第一个DLL切换到ANSI,因为我们在C#应用程序中使用Unicode,这是我们的标准。

我不明白对二阶DLL的敏感性。有人可以为我阐明这一点吗?

我使用这个类来动态链接到DLL:

static class NativeMethods
        {
            [DllImport("kernel32", SetLastError = true)]
            public static extern bool FreeLibrary(IntPtr hModule);

            [DllImport("kernel32", SetLastError = true)]
            public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

            [DllImport("kernel32", SetLastError = true)]
            public static extern IntPtr LoadLibrary(string dllToLoad);
        }

与代表相似:

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        private delegate int ExampleFunction();

并将CharSet.Auto切换为.Ansi或.Unicode无效。

与函数调用等:

m_pDll = NativeMethods.LoadLibrary(@strDLLName);
                if (m_pDll == IntPtr.Zero) this.Close();

                IntPtr pAddressForExampleFunction = NativeMethods.GetProcAddress(m_pDll, "ExampleFunction");
                if (pAddressForExampleFunction == IntPtr.Zero) this.Close();
m_ExampleFunction = (ExampleFunction)Marshal.GetDelegateForFunctionPointer(pAddressForExampleFunction, typeof(ExampleFunction));

带函数调用:

m_ExampleFunction();

其他代码。

编辑:

根据要求,C ++ EXE对应部分:

在.h文件中,定义为成员:

ExampleFunction pExampleFunction;   

typedef BOOL __declspec(dllimport) (*ExampleFunction)();

pExampleFunction定义为:

pExampleFunction= (ExampleFunction) ::GetProcAddress(m_hDll,"ExampleFunction");

使用此电话,之前:

m_hDll = AfxLoadLibrary(m_DllName);
答案

最有可能的问题是在两个非托管dll之间发生,因为它们之间的字符串数据传输不一致。

ANSI / Unicode dll标志是编译时属性。编译器根据此标志选择类型和函数。 TCHAR for Unicode编译为wchar_t,ANSI编译为char。例如。如果一个dll期望获得符号长度的wchar_t*,那么这种差异可能会导致出界问题,但实际接收的值是char*。这是未定义的行为,可能导致应用程序崩溃。

此外,许多Win API函数有两个版本的xxxW用于Unicode,xxxA用于ANSI。例如:

#ifdef UNICODE
   #define MessageBox MessageBoxW
#else
   #define MessageBox MessageBoxA
#endif. 

在C#端,CharSet属性控制字符串编组并确定平台调用如何在DLL中查找函数名称。它不会影响非托管C ++ DLL中的进一步字符串操作。方法

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private delegate int ExampleFunction();

没有任何条件可以编组,所以CharSet不会影响它。如果在非托管C ++端有两个这种方法的实现,可能会有区别:ANSI的ExampleFunctionA和Unicode的ExampleFunctionW

以上是关于C#EXE w / Unmanaged C ++ Unicode DLL链接到非托管C ++ ANSI DLL崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何用C语言实现CMD.EXE调用

.NET 无法在同一目录中找到非托管 DLL

Microsoft C 编译器 (cl.exe):可以限制每个文件 (/Wall) 的警告范围吗?

[W班]第二次结对作业成绩评价

如何将 C/C++ dll 导入 .NET 应用程序

c#泛型中非托管和结构约束之间的区别