Позднее связывание C ++ DLL с C # - функция всегда возвращает true - PullRequest
3 голосов
/ 20 ноября 2011

У меня есть DLL, которая имеет это в своем файле h:

extern "C" __declspec(dllexport) bool Connect();

и в файле c:

extern "C" __declspec(dllexport) bool Connect()
{
     return false;  
}

В c # у меня есть следующий код:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ConnectDelegate();

private ConnectDelegate DLLConnect;

public bool Connect()
{
    bool l_bResult = DLLConnect();
    return l_bResult;
}

public bool LoadPlugin(string a_sFilename)
{
   string l_sDLLPath = AppDomain.CurrentDomain.BaseDirectory;

   m_pDLLHandle = LoadLibrary(a_sFilename);
   DLLConnect = (ConnectDelegate)GetDelegate("Connect", typeof(ConnectDelegate));
   return false;
}

private Delegate GetDelegate(string a_sProcName, Type a_oDelegateType) 
{
    IntPtr l_ProcAddress = GetProcAddress(m_pDLLHandle, a_sProcName);
    if (l_ProcAddress == IntPtr.Zero)
       throw new EntryPointNotFoundException("Function: " + a_sProcName);

    return Marshal.GetDelegateForFunctionPointer(l_ProcAddress, a_oDelegateType);
}

По какой-то странной причине, функция connect всегда возвращает true независимо от того, какое значение возвращается в C ++. Я пытался изменить соглашение о вызовах на StdCall в C #, но проблема остается.

Есть идеи?

1 Ответ

4 голосов
/ 20 ноября 2011

Проблема, вероятно, заключается в "bool". В MSVC sizeof (bool) равен 1, а sizeof (BOOL) равен 4! BOOL - это тип, используемый Windows API для выражения логического значения, и представляет собой 32-разрядное целое число. Таким образом, C # ожидает 32-битное значение, но вы выделяете 1-байтовое значение, поэтому вы получаете «мусор».

Существует два решения:

1) вы меняете код C, чтобы вернуть BOOL или int.

2) Вы меняете код C #, добавляя атрибут [return:MarshalAs(UnmanagedType.I1)] к функциям импорта dll.

...