У меня есть исполняемый файл C#, который загружается в DLL, которая является unicode неуправляемой C++ DLL. Эта неуправляемая C++ DLL также ссылается на другую DLL, неуправляемую DLL на C++, которая, как оказалось, является ANSI.C# EXE w/Unmanaged C++ Unicode DLL ссылка на неуправляемый C++ ANSI DLL crash
Когда я запускаю свой исполняемый файл C#, программа заканчивается сбоем в ANSI-части DLL-вызовов (пока я еще не смог удалить исключение). Однако, просто переключив ANSI DLL на Unicode, все работает, за исключением того факта, что есть третья DLL, которая из SDK от другой компании, которая имеет очевидную чувствительность к unicode/ANSI, поэтому она лучше всего работает, если вызывающая DLL находится в ANSI.
Итак, у нас есть одна исполняемая функция вызова только в одной неуправляемой DLL-библиотеке Unicode, которая служит в качестве оболочки для неуправляемой ANSI C++ DLL, которая является оболочкой для последней неуправляемой DLL, о которой у нас нет информации.
Переключение двух промежуточных библиотек DLL в уникод исправляет сбой только в случае его отказа с третьей отдельной DLL-производителем (но не катастрофически с исключением, они просто выводятся неправильно). Мы не можем переключить первую DLL на ANSI, потому что мы используем Unicode в нашем приложении C#, и это наш стандарт по всем направлениям.
Я не понимаю чувствительность к 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();
в другом месте в коде.
Edit:
В соответствии с просьбой C++ EXE Контрагент:
В файле .h, определяется как члена:
ExampleFunction pExampleFunction;
с
typedef BOOL __declspec(dllimport) (*ExampleFunction)();
pExampleFunction определяется как:
pExampleFunction= (ExampleFunction) ::GetProcAddress(m_hDll,"ExampleFunction");
, используя этот вызов, до:
m_hDll = AfxLoadLibrary(m_DllName);
(...) Тем не менее, просто переключая ANSI DLL в Unicode, все работает для того, что есть третья DLL, которая из SDK от другой компании, которая имеет кажущуюся чувствительность к кроме unicode/ANSI, поэтому он лучше всего работает, если вызывающая DLL находится в ANSI. (...) Это утверждение для меня не имеет смысла ... если эта третья dll не является COM-объектом, который вы используете через библиотеку типов, существует только один правильный способ передать строковые параметры для функций из этой DLL. Если вы передадите неправильный тип строки, он будет аварийно завершен. – yms
Даже если эта «чувствительная» dll предоставляет функции ansi и unicode (примерA (LPCSTR val) vs exampleW (LPCWSTR val)), вашей «клиентской» dll по-прежнему необходимо будет выбрать нужную функцию в соответствии с конфигурацией сборки. – yms
Для строгого читателя: Я знаю, что я «злоупотребляю» термином «Юникод» здесь ... пожалуйста, не сосредотачивайтесь на этом. – yms