Не удалось найти точку входа при вызове С++ dll в С#

Я пытаюсь изучить P/Invoke, поэтому я создал простую dll в С++

KingFucs.h:

namespace KingFuncs
{
    class KingFuncs
    {
    public:
        static __declspec(dllexport) int GiveMeNumber(int i);
    };
}

KingFuns.cpp:

#include "KingFuncs.h"
#include <stdexcept>

using namespace std;

namespace KingFuncs
{
    int KingFuncs::GiveMeNumber(int i)
    {
        return i;
    }
}

Итак, он компилируется, затем я скопировал эту dll в мою папку отладки WPF с кодом:

[DllImport("KingFuncDll.dll", EntryPoint = "GiveMeNumber", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int GiveMeNumber(
              int i
              );

И называя его нажатием кнопки:

private void Button_Click(object sender, RoutedEventArgs e)
{
    int num = GiveMeNumber(123);
}

Но это дает мне исключение:

Не удалось найти точку входа с именем 'GiveMeNumber' в DLL 'KingFuncDll.dll'.

Действительно.... что я сделал неправильно... Очевидно, что он может найти DLL, иначе это будет еще одно исключение. Но мое имя метода точно такое же... Я не могу придумать другую причину.

Ответы

Ответ 1

Вам нужно использовать extern "C", когда вы экспортируете свою функцию, чтобы подавить сбой имени С++. И вы также не должны пытаться p/invoke членам класса. Вместо этого используйте бесплатные функции:

extern "C" {
    __declspec(dllexport) int GiveMeNumber(int i)
    {
        return i;
    }
}

На управляемой стороне ваш атрибут DllImport ошибочен. Не используйте SetLastError только для Win32 API. Не утруждайте настройкой CharSet, если нет текстовых параметров. Нет необходимости в ExactSpelling. И вызывающее соглашение предположительно Cdecl.

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int GiveMeNumber(int i);

Ответ 2

Проблема в том, что вы объявляете "функцию" С++ внутри класса С++ и сообщаете P/Invoke использовать StdCall.

Попробуйте объявить функцию С++ вне класса и экспортировать ее так же, как и вы. Тогда ваш код должен работать.

Если у вас действительно есть функция С++ внутри класса, взгляните на CallingConvention.ThisCall. Но тогда вы отвечаете за создание неуправляемого экземпляра класса и передаете его в качестве первого параметра вашего вызова P/Invoke

Ответ 3

Имя точки входа dll файла указывается в .exp файле, который находится в папке отладки, где присутствуют другие исходные файлы. Если самосвал не работает, вы можете попробовать это.