Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c#中正确制作Dllimport?_C#_Asp.net_C++_Visual Studio 2010_Dllimport - Fatal编程技术网

如何在c#中正确制作Dllimport?

如何在c#中正确制作Dllimport?,c#,asp.net,c++,visual-studio-2010,dllimport,C#,Asp.net,C++,Visual Studio 2010,Dllimport,我在从c++项目到我的c#项目构建正确的.dll时遇到了一些问题。 我使用了c++项目属性,得到了一个.dll文件,可以在我的c#web项目中添加和引用。我使用Dllimport对.dll进行函数调用,如下所示: [DllImport("Filename.dll", CharSet = CharSet.Ansi)] static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src,

我在从c++项目到我的c#项目构建正确的.dll时遇到了一些问题。 我使用了c++项目属性,得到了一个.dll文件,可以在我的c#web项目中添加和引用。我使用Dllimport对.dll进行函数调用,如下所示:

[DllImport("Filename.dll", CharSet = CharSet.Ansi)]
static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src, 
                             int srcLen, 
                             [MarshalAs(UnmanagedType.LPWStr)] StringBuilder dst,
                             int dstLen)

C++函数头为:

__declspec(dllimport) void Function1(unsigned char *src, 
                     unsigned long srclen, 
                     unsigned char *dst, 
                     unsigned long dstlen);
我用以下命令调用c#中的函数1:

string strSrc = "Something";
StringBuilder strDest = new StringBuilder(kryptlen-1);
int l = strSrc.Length();
Function1(strSrc, l, strDest, l);
没有异常或错误发生,尽管我没有得到预期的输出。函数是一种解密方法,它接受加密字符串(src)并返回该字符串的解密版本(dst)

是我生成.dll文件的方式还是我调用函数的方式不对?我没有主意了,我试过很多组合


谢谢你的建议

UnmanagedType.LPWStr
从哪里来?C++声明中没有宽字符串。您还将传递源长度两次,而变量名表明您需要源长度和目标缓冲区容量

如果
src
是您所说的加密数据,则正确的p/invoke签名可能是:

[DllImport("Filename.dll", CallingConvention = CallingConvention.CDecl)]
static extern void Function1(byte[] src, 
                             UInt32 srcLen,
                             [MarshalAs(UnmanagedType.LPStr)] StringBuilder dst,
                             UInt32 dstLen)

试图将二进制数据强制转换为Unicode字符串是一个失败的主张。

UnmanagedType.LPWStr是从哪里来的?C++声明中没有宽字符串。您还将传递源长度两次,而变量名表明您需要源长度和目标缓冲区容量

如果
src
是您所说的加密数据,则正确的p/invoke签名可能是:

[DllImport("Filename.dll", CallingConvention = CallingConvention.CDecl)]
static extern void Function1(byte[] src, 
                             UInt32 srcLen,
                             [MarshalAs(UnmanagedType.LPStr)] StringBuilder dst,
                             UInt32 dstLen)

试图将二进制数据强制转换为Unicode字符串是一种失败的做法。

C++默认情况下,除非更改使用调用方(Cdecl)调用约定。您的C++代码不会更改调用约定。默认情况下,C#代码(除非更改)将使用被调用方约定(StdCall)

虽然这可能不是问题所在,但您拥有它在技术上仍然是不正确的。即使您要解决当前的问题,您也可能会因为呼叫约定而最终遇到问题

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src,                               int srcLen,                               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder dst,                              int dstLen) 
没有发生异常或错误, 虽然我没有得到我的输出 期望。该函数是一个 采用 加密字符串(src)并返回 此文件的解密版本(dst)

你到底得到了什么

调用约定问题的解决方案是声明调用约定

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src,                               int srcLen,                               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder dst,                              int dstLen) 

默认情况下,除非更改,否则C++使用调用方(Cdecl)调用约定。您的C++代码不会更改调用约定。默认情况下,C#代码(除非更改)将使用被调用方约定(StdCall)

虽然这可能不是问题所在,但您拥有它在技术上仍然是不正确的。即使您要解决当前的问题,您也可能会因为呼叫约定而最终遇到问题

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src,                               int srcLen,                               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder dst,                              int dstLen) 
没有发生异常或错误, 虽然我没有得到我的输出 期望。该函数是一个 采用 加密字符串(src)并返回 此文件的解密版本(dst)

你到底得到了什么

调用约定问题的解决方案是声明调用约定

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] static extern void Function1([MarshalAs(UnmanagedType.LPStr)] string src,                               int srcLen,                               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder dst,                              int dstLen) 

经过一段时间前后更改设置后,我注意到我必须首先使用的数据与解密和加密后的数据相同。所以我意识到加密/解密是有效的。问题在于数据。当我得到正确的数据时,我得到了正确的输出

这是我现在坚持的最终设置,希望它能帮助某人:

cryptedString = "CryptedStringFromDataBase";
StringBuilder decryptedString = new StringBuilder(300);
Decrypt(cryptedString, (uint)cryptedString.Length, decryptedString, 300);

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void Decrypt(string src, UInt32 srcLen, [MarshalAs(UnmanagedType.LPStr)] StringBuilder dst, UInt32 dstLen);

经过一段时间前后更改设置后,我注意到我必须首先使用的数据与解密和加密后的数据相同。所以我意识到加密/解密是有效的。问题在于数据。当我得到正确的数据时,我得到了正确的输出

这是我现在坚持的最终设置,希望它能帮助某人:

cryptedString = "CryptedStringFromDataBase";
StringBuilder decryptedString = new StringBuilder(300);
Decrypt(cryptedString, (uint)cryptedString.Length, decryptedString, 300);

[DllImport("Filename.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void Decrypt(string src, UInt32 srcLen, [MarshalAs(UnmanagedType.LPStr)] StringBuilder dst, UInt32 dstLen);

可以在C++项目设置中打开非托管调试,并从C代码到C++代码。马丁:我可以在任何地方为web应用程序这样做吗?找不到。事实上我想你可以。在Web选项卡的底部有一个带有本机代码选项的调试器部分。然而,if将避免在web应用程序中进行类似这样的小测试。小型控制台应用程序或测试项目更适合测试代码片段。我启用了本机代码,但当我调用dll的函数并按F11时,它不会跳转到dll中。请确保本机dll是调试版本,并且符号(PDB文件)可用。如果您正在调试Web应用程序,我强烈建议在控制台应用程序中进行测试,以从公式中删除ASP.NET。您可以打开C项目设置中的非托管调试,并从C代码到C++代码。马丁:我可以在任何地方为web应用程序这样做吗?找不到。事实上我想你可以。在Web选项卡的底部有一个带有本机代码选项的调试器部分。然而,if将避免在web应用程序中进行类似这样的小测试。小型控制台应用程序或测试项目更适合测试代码片段。我启用了本机代码,但当我调用dll的函数并按F11时,它不会跳转到dll中。请确保本机dll是调试版本,并且符号(PDB文件)可用。如果您正在调试web应用程序,我强烈建议您在控制台应用程序中进行测试,以从equation.UnmanagedType.LPWStr中删除ASP.NET,我正在尝试所有替代方法。我也尝试过LPStr。尝试将第二个长度参数更改为缓冲区大小(尝试使用200)。我得到不同的输出,但仍然不正确