gpt4 book ai didi

c# - 难以从 C# 调用非托管 dll

转载 作者:太空狗 更新时间:2023-10-29 21:51:09 25 4
gpt4 key购买 nike

我要睡眼惺忪地想弄清楚为什么我不能从我的 C# 应用程序中调用旧 C++ .dll 中的外部方法。

这是函数头:

int __export FAR PASCAL SimplePGPEncryptFile(
HWND hWnd1,
LPSTR InputFileName,
LPSTR OutputFileName,
BOOL SignIt,
BOOL Wipe,
BOOL Armor,
BOOL TextMode,
BOOL IDEAOnly,
BOOL UseUntrustedKeys,
LPSTR RecipientList,
LPSTR SignerKeyID,
int SignerBufferLen,
LPSTR SignerPassphrase,
int SignerPwdBufferLen,
LPSTR IDEAPassphrase,
int IDEAPwdBufferLen,
LPSTR PublicKeyRingName,
LPSTR PrivateKeyRingName);

这是我的 C# 声明:

        [DllImport("smplpgp_32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int SimplePGPEncryptFile(
IntPtr hWnd1,
[MarshalAs(UnmanagedType.LPStr)] string InputFileName,
[MarshalAs(UnmanagedType.LPStr)] string OutputFileName,
bool SignIt,
bool Wipe,
bool Armor,
bool TextMode,
bool IDEAOnly,
bool UseUntrustedKeys,
[MarshalAs(UnmanagedType.LPStr)] string RecipientList,
[MarshalAs(UnmanagedType.LPStr)] string SignerKeyID,
int SignerBufferLen,
[MarshalAs(UnmanagedType.LPStr)] string SignerPassphrase,
int SignerPwdBufferLen,
[MarshalAs(UnmanagedType.LPStr)] string IDEAPassphrase,
int IDEAPwdBufferLen,
[MarshalAs(UnmanagedType.LPStr)] string PublicKeyRingName,
[MarshalAs(UnmanagedType.LPStr)] string PrivateKeyRingName);

当我调用此方法时,出现以下两个错误之一(在 header 中声明):

#define SIMPLEPGPENCRYPTFILE_RECIPIENTLISTDOESNOTENDWITHNEWLINE    408
#define SIMPLEPGPENCRYPTFILE_RECIPIENTLISTDOESNOTSTARTWITHGOODCODECHAR 409

这也在 header 中定义为常量:

#define INCLUDE_ONLYUSERIDS 1

这是已知可以调用此函数的 C++ 代码:

    char recipients[512];
recipients[0] = INCLUDE_ONLYUSERIDS;
strcat(strcpy(&recipients[1], rID), "\n"); \\ rID is equal to "CA"
return 0 == SimplePGPEncryptFile(INI.m_hWnd,
(char*)plain, (char*)cipher,
0,
0,
1,
0,
0,
1, // UseUntrustedKeys
recipients,
0, 0,
0, 0,
0, 0,
PGPKM.pub, 0); //PGPKM.pub is declared earlier

将此传递给“RecipientList”参数会给我“409”错误:

string recipientList = "1CA\n\0";

将此传递给“RecipientList”参数会给我“408”错误:

char[] recipients = new char[512];
recipients[0] = '1';
recipients[1] = 'C';
recipients[2] = 'A';
recipients[3] = '\n'; // also tried '\r', then '\n'
recipients[4] = Char.MinValue;
string paramValue = recipients.ToString();

谁能发现我明显的疏忽?我觉得我已经拥有解决此问题所需的一切,但没有任何事情按预期进行。

旁注:我在同一个 .dll 中成功调用了不同的函数。此外,我还尝试使用 StringBuilder 构造 RecipientList 参数。

感谢您的任何建议!

最佳答案

TLDR:

string recipientList = (char) 1 + "CA\n\0";

根据 Jeffora 的评论做了一些挖掘......他可能是对的,我的第一个建议可能不会给你买任何东西。我写了一些测试代码,这是我发现的:

当您使用此代码时:

string recipientList = "1CA\n\0";

作为 LPStr 编码(marshal)处理后,您在函数内部最终得到的字节是:

49-67-65-10-0

这看起来像你想要的。

当您使用此代码时:

char[] recipients = new char[512];
recipients[0] = '1';
recipients[1] = 'C';
recipients[2] = 'A';
recipients[3] = '\n'; // also tried '\r', then '\n'
recipients[4] = Char.MinValue;
string paramValue = recipients.ToString();

作为 LPStr 编码(marshal)处理后,您在函数内部获得的字节是:

83-121-115-116-101-109-46-67-104-97-114-91-93

这是“System.Char[]”的 ASCII。因此,您肯定需要使用编码器将 char[] 转换为您想要的字符串。

至于为什么第一个字符串不起作用...我怀疑您的 DLL 确实在寻找值“1”,而不是“1”的 ascii 字符 (49)。在有效的代码中,您说:

recipients[0] = INCLUDE_ONLYUSERIDS;

其中 INCLUDE_ONLYUSERIDS = 1

试试这个:

string recipientList = (char) 1 + "CA\n\0";


原答案:
我认为问题在于 Char.ToString() 将 char 视为 unicode 字符,但您正在编码为 LPStr,而不是 LPWStr。 LPStr 正在寻找一串 ANSII 字符。

要解决此问题,请尝试使用字节数组。

byte[] recipients= new byte[512];
...
// Pass this string to SimplePGPEncryptFile
string recipientsToPass = System.Text.ASCIIEncoding.ASCII.GetString(recipients);

关于c# - 难以从 C# 调用非托管 dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4394915/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com