2011-01-19 127 views
1

我有一个问题调用C#应用程序内的c + + dll函数。我打电话给c#里面的函数就像这样:在64位.net应用程序通过c + + 64位DLL pInvoke

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

它被导出到C++ dll中,如下所示。

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,并提前致谢。

+0

返回char *的C函数非常麻烦。经典的错误是返回一个指向局部变量的指针。从C程序调用时有一些工作的可能性,在被调用时为零。即使它由C代码正确完成,并且它使用malloc()来分配字符串缓冲区,但仍然存在无法解决的内存泄漏。你需要代码作者的帮助。 – 2011-01-19 18:01:19

回答

3

我认为你需要的第一行更改为:

[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

(我真的不看你的返回类型在第一次回答这个问题的时候。)

+1

仍然得到相同的例外...你的建议是有道理的,但我真的很惊讶,这是行不通的嗨 – sringer 2011-01-19 15:50:32

+0

字符串类型是`const char *`类型在技术上``LPCSTR` – Aphex 2011-01-19 15:50:46

0

看来你要const char *类型(LPCSTR)的返回值存储到IntPtr类型(通常。用于HANDLE S,不LPSTR S)试试这个:

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

还要记住,如果任何参数是越来越写入,你需要它的类型前加out,即..., out String message)