Мне предоставили библиотеку DLL, которая должна вызываться C # et al. DLL содержит два метода следующим образом
extern "C" {
__declspec(dllexport) BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
__declspec(dllexport) void G();
}
class GrouperServer {
public:
BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
void G();
}
BSTR GrouperServer::GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr) {
CString strResult = "";
char* sz;
SetVars(bDiagErr, bProcErr);
if (sz = ::GroupInit((char*)bstrIniFile, 1))
strResult = sz;
return strResult.AllocSysString();
}
void G() {
MessageBox(0, "And text here", "MessageBox caption", MB_OK);
}
Я пытаюсь вызвать эти библиотеки DLL из C #, сначала определив класс:
public class GrouperServer {
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void G();
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
string strCmdFile, bool bAllowBadDiagCodes, bool bAllowBadProcCodes);
}
и делать
this.strCommandFilePath = "C:\\MyDir\\MyCommandFile.txt";
Grouper.GrouperServer.G();
Grouper.GrouperServer.GroupInit(this.strCommandFilePath, true, true);
Вызов метода G()
работает, и я получаю окно сообщения, но для вызова GroupInit()
, Я получил
Необработанное исключение типа «System.EntryPointNotFoundException» произошло в DrGroupIN.exe. Дополнительная информация: Невозможно найти точку входа с именем «GroupInit» в DLL «GrouperServer.dll».
Как я могу вызвать второй метод GrouInit(...)
с правильными параметрами в этом случае?
Редактировать 1.
Я также пытался
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GroupInit(
string strCmdFile, bool bAllowBadDiagCodes, bool bAllowBadProcCodes);
где это называется через:
IntPtr ptr = Grouper.GrouperServer.GroupInit(this.strCommandFilePath, true, true);
string strString = Marshal.PtrToStringBSTR(ptr);
Marshal.FreeBSTR(ptr);
Но это тоже выдает ошибку выше.
Изменить 2.
Я также пытался
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
[MarshalAs(UnmanagedType.LPTStr)]string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes);
Но это тоже выдает ошибку выше.
Мне кажется, что вы не можете вызвать эту DLL с помощью C #. DLL экспортирует функции-члены класса. И вы не можете создать экземпляр этого класса.
Я вижу следующие варианты:
Тем не менее, эти декларации, кажется, находятся в конфликте:
extern "C" {
__declspec(dllexport) BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
__declspec(dllexport) void G();
}
class GrouperServer {
public:
BSTR GroupInit(LPCTSTR bstrIniFile, bool bDiagErr, bool bProcErr);
void G();
}
Кажется, что первая пара объявлений не является функциями-членами. Но за ними следует класс с функциями-членами с одинаковыми именами. Вам необходимо четко определить, какие функции вы пытаетесь вызвать.
Возможно, DLL уже содержит функции, не являющиеся членами, которые оборачивают функции-члены. В этом случае вам просто нужно узнать имена, по которым они экспортируются. Используйте Dependency Walker, чтобы сделать это.
Итак, как объявить p / invoke. Вам необходимо знать используемый набор символов и имя, по которому экспортируется функция. Давайте предположим, Unicode. P / invoke будет:
[DllImport("GrouperServer.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "<exported name goes here>")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GroupInit(
[MarshalAs(UnmanagedType.LPWStr)]
string strCmdFile,
bool bAllowBadDiagCodes,
bool bAllowBadProcCodes
);
Других решений пока нет …