PInvoke в 64-битном приложении .net через c ++ 64-битную DLL - PullRequest
1 голос
/ 19 января 2011

У меня проблема с вызовом функции в dll c ++ внутри приложения c #. Я вызываю функцию внутри c # примерно так:

[DllImport("cryptopp.dll")]
public static extern IntPtr RSAEncryptString(string filename, string seed, string message);

Экспортируется в dll c ++, как показано ниже.

extern "C" __declspec(dllexport) const char* __cdecl RSAEncryptString(const char *pubFilename, const char *seed, const char *message);

Однако, когда я пытаюсь вызвать это, я получаю следующее: «Внешний компонент выдал исключение». исключение, которое не очень наглядно и крайне бесполезно.

Когда я открываю dll в средстве просмотра экспорта, он показывает все другие экспортируемые функции с полностью определенными количественными объявлениями (IE public: void __cdecl CryptoPP :: X509PublicKey :: `vbase destructor '(void) __ptr64), кроме Я вызываю функцию, которая просто отображает имя функции RSAEncryptString.

Это единственная возможная проблема, которую я вижу, кроме, возможно, неправильного вызова функции с недопустимым объявлением на стороне c #. Я использую System.Runtime.InteropServices.Marshal неправильно?

Пожалуйста, помогите <3 и заранее спасибо. </p>

Ответы [ 2 ]

3 голосов
/ 19 января 2011

Я думаю, что вам нужно изменить первую строку на:

[DllImport("cryptopp.dll",
    CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]

Если вы хотите получить очень информативный, вы также можете добавить эти:

public static extern IntPtr RSAEncryptString(
    [In, MarshalAs(UnmanagedType.LPStr)] string filename,
    [In, MarshalAs(UnmanagedType.LPStr)] string seed,
    [In, MarshalAs(UnmanagedType.LPStr)] string message);

IIRC думаю, что CharSet должен позаботиться о кодировке для вас, но если это не так, используйте MarshalAs также, как показано выше.


Редактировать:

О, я думаюЯ понял, почему вы все еще получаете ошибку!В вашем коде все еще были вышеуказанные проблемы, но он по-прежнему ошибочен, потому что вы не можете вернуть объект string, поскольку он не является управляемым объектом;вам нужно вернуть указатель (например, IntPtr), а затем использовать Marshal.PtrToStringAnsi!

(я действительно не смотрел ваш тип возврата, когда отвечал на это сначала.)

0 голосов
/ 19 января 2011

Похоже, вы пытаетесь сохранить возвращаемое значение типа const char * (LPCSTR) в типе IntPtr (обычно используется для HANDLE с, а не LPSTR с.) Попробуйте это:

[DllImport("cryptopp.dll", CharSet = CharSet.Auto)]
public static extern String RSAEncryptString(String filename, String seed, String message);

Также имейте в виду, что если записывается какой-либо аргумент, вам необходимо добавить out перед его типом, т.е. ..., out String message)

...