У меня странная проблема. У меня есть C ++ DLL, которую я импортирую в C # библиотеку, используя импорт DLL. Если я укажу точку входа, все будет работать как положено, вот пример:
internal static class UnsafeMethods
{
[DllImport("GoodSchool.dll", EntryPoint = @"?AddNum@@YAHHH@Z")]
public static extern int AddNum(int num1, int num2);
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(UnsafeMethods.AddNum(4,5));
}
}
Однако, если я использую упрощенный импорт, как здесь:
[DllImport("GoodSchool.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int AddNum(int num1, int num2);
Я получаю знакомое сообщение об ошибке:
Необработанное исключение: System.EntryPointNotFoundException: невозможно найти точку входа с именем «AddNum» в DLL «GoodSchool.dll»
Я использовал зависимости, чтобы убедиться, что метод выставлен правильно, и я расшифровал нотацию, чтобы проверить параметры и соглашение об именах — все кажется хорошим.
Подпись функции в C ++ очень проста:
__declspec(dllexport) int AddNum(int num1, int num2);
Любые предложения, как я могу вызвать этот метод в C # без предоставления оформленного имени как EntryPoint? Что я делаю не так? Я не хочу использовать экспорт «C», так как я понимаю, что оформленное имя функции прекрасно подходит для использования с DllImport.
C ++ изменяет имена функций для учета перегрузки имен функций. В конце концов, если DLL была
__declspec(dllexport) int AddNum(int num1);
__declspec(dllexport) int AddNum(int num1, int num2);
которые бы AddNum
Ссылаться на?
Символ ?AddNum@@YAHHH@Z
является искаженным (украшенным) именем, отображаемым в неуправляемой DLL.
https://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B
Ваша DLL не экспортирует то, что называется AddNum
,
Декорированное имя функции отлично подходит для DllImport
, как вы можете видеть по тому, что вы это делаете. Но это требует от вас уточнить оформленное имя функции в импорте. Недоукрашенное имя не существует в отношении компоновщика (статического или динамического): AddNum
это просто не символ, который выставляет ваша библиотека.
Если вы вместо этого хотите сделать то, что вы просите:
вызвать этот метод в C # без предоставления оформленного имени как EntryPoint?
тогда вы не можете позволить C ++ искажать имя в первую очередь. Вы можете или укажите оформленное имя в DllImport
или же использование extern "C"
связь с кодом C ++. Вы должны выбрать один или другой.