C# P\Invoke DLL нет точки входа в C++?
У меня есть C++ Dll "TheFoo.dll" с методом "Foo()"
У меня есть доступ к другому коду C++, который использует этот метод, просто вызывая:
Foo();
Я считаю, что метод имеет:
__declspec( dllexport )
Итак, после прочтения P/Invoke я подумал, что смогу просто вызвать тот же метод из моего кода C#:
namespace PInvokeExample1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport(@"C:\MyFolder\TheFoo.dll")]
public static extern
void Foo();
private void button1_Click(object sender, RoutedEventArgs e)
{
Foo();
}
}
}
Когда я запускаю его, я получаю сообщение об ошибке:
Unable to find an entry point named 'Foo' in DLL 'C:\MyFolder\TheFoo.dll'.
Любые идеи, почему это не найдено?
3 ответа
Вы должны предоставить больше информации о вашем C++. Попробуйте использовать extern "C" __declspec(dllexport)
вместо. C++ экспортирует со странными именами, поэтому с помощью extern "C"
избегает этого
Язык C++ поддерживает перегрузку, так же как и C#. Вы можете экспортировать функцию void Foo(int)
и функция void Foo(double)
, Очевидно, что эти две функции нельзя было экспортировать как "Foo", клиент DLL не знал бы, какую из них выбрать. Так что нет.
Компилятор C++ решает эту проблему, декорируя имя функции. Добавление дополнительных символов, которые отличают Foo (int) от Foo (double). Вы можете увидеть эти украшенные имена, запустив Dumpbin.exe /exports foo.dll
из командной строки Visual Studio, в которой указано имя экспортируемых функций. Предполагая, что ваша декларация была актуальна, вы увидите ?Foo@@YAXXZ
,
Таким образом, соответствующее объявление в вашей программе на C# должно быть:
[DllImport("foo.dll", EntryPoint = "?Foo@@YAXXZ",
ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void Foo();
Существуют способы изменить объявление функции C++, чтобы упростить объявление C#. Что на самом деле не очень хорошая идея, эти украшенные имена на самом деле помогают ловить ошибки.
Если вы не объявили это extern "C" в вашей dll, его имя, вероятно, было "искажено". Вы можете использовать что-то вроде Dependency Walker, чтобы увидеть, какие символы экспортирует ваша dll.