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.

Другие вопросы по тегам