Не удалось найти точку входа при вызове С++ 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 файле, который находится в папке отладки, где присутствуют другие исходные файлы. Если самосвал не работает, вы можете попробовать это.