C# 中调用 API 时的出参类型转换

youzelin 2009-03-03 02:17:34
这个问题是关于公司业务的,需要做一个接口,我已知有一个 API 函数,其 C++ 中的原型是这样的:


long QuerySKInfo(LPSTR pInputData, long pInputLen, LPSTR pOutputData, long pOutputLen);


问题在于:pOutputData 和 pOutputLen 都是出参,但是我查了一下,LPSTR 对应的 C# 类型是 string 类型,long 对应的是 int,所以如下:


[DllImport(@"..\skComm.dll", EntryPoint = "QuerySKInfo")]
public static extern int QuerySKInfo(string pInputData, int pInputLen, string pOutputData, int pOutputLen);


但是这样我就取不到 pOutputData 的值,因为在 C# 里面,string pOutputData 不是出参,但是如果我加了 ref 或者 out,就会报“只读内存”之类的错,我也试着将 string pOutputData 改成 byte[] pOutputData,但是依然取不到值,我不知道应该如何解决,请高人指教,谢谢!
...全文
222 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
yueyebohe 2009-03-09
  • 打赏
  • 举报
回复
都是高人啊,学习来了~!
RFEZGC 2009-03-08
  • 打赏
  • 举报
回复
第一个参数因为是输入的参数 可以用stringBUILDER ,但因为是入参,字符的长度是固定的,所以我觉得用
string合适点,第二个是指针,对于直类型要加ref
第三个是出参,字符是没有固定长度的所以一定要用STRINGBUILDER
第四个是出参,指针 要用out 回者ref ,我规范点用out
注意string 和stringBuilder 是引用类型,对于在API(不知道你这个原形是不是API函数,还是C++的dll)
不能用out/ref修饰,否则就是二级寻址
抱歉,上面那个忘了写返回直
RFEZGC 2009-03-08
  • 打赏
  • 举报
回复
long QuerySKInfo(LPSTR pInputData, long pInputLen, LPSTR pOutputData, long pOutputLen);


static extern QuerySKInfo(
string InputData,
ref int pDatalen,
stringBuilder pOutputData,
out int outDataLen
);
youzelin 2009-03-05
  • 打赏
  • 举报
回复
谢谢!谢谢各位!

relive_qiankai:你的方法和我咨询的另外一家接口合作的公司的参考代码一样,也是用

[MarshalAs(UnmanagedType.LPStr)]string

但是今天试了一天,没有成功,也不知道是什么问题,应该是可以的,因为对方就是这样用的,郁闷......
还有他们的代码接口是这样转的



icehawk:你的方法和 relive_qiankai 有点差不多,明天到公司试试 :),不知道能不能成功

bomdy:居然不敢相信,微软都这样说,但是我的确试过 StringBuilder,未遂 :( ,可能是没与先申请空间,明天再试试


bomdy 2009-03-03
  • 打赏
  • 举报
回复
用StringBuilder,要预先申请空间

http://msdn.microsoft.com/en-us/library/x3txb6xc.aspx

public class LibWrap
{
[ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )]
public static extern int GetSystemDirectory( StringBuilder
sysDirBuffer, int size );
[ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )]
public static extern IntPtr GetCommandLine();
}

public class App
{
public static void Main()
{
// Call GetSystemDirectory.
StringBuilder sysDirBuffer = new StringBuilder( 256 );
LibWrap.GetSystemDirectory( sysDirBuffer, sysDirBuffer.Capacity );

// Call GetCommandLine.
IntPtr cmdLineStr = LibWrap.GetCommandLine();
String commandLine = Marshal.PtrToStringAuto( cmdLineStr );
}
}
icehawk 2009-03-03
  • 打赏
  • 举报
回复
[Out, MarshalAs(UnmanagedType.LPStr)]StringBuilder pInputData
relive_qiankai 2009-03-03
  • 打赏
  • 举报
回复
前面加 System.Runtime.InteropServices
LPSTR转为C#格式 [MarshalAs(UnmanagedType.LPStr)] string

用这个试试
wo789 2009-03-03
  • 打赏
  • 举报
回复
long QuerySKInfo(LPSTR pInputData, long pInputLen, LPSTR* pOutputData, long pOutputLen);


让他们把C++接口改成上面那些C#就可以用下面的方式调用了:
[DllImport(@"..\skComm.dll", EntryPoint = "QuerySKInfo")]
public static extern int QuerySKInfo(string pInputData, int pInputLen, ref string pOutputData, int pOutputLen);
relive_qiankai 2009-03-03
  • 打赏
  • 举报
回复

显示转换试试
zgke 2009-03-03
  • 打赏
  • 举报
回复
StringBuilder pDataInput = new StringBuilder("0001");
StringBuilder pDataOutput = new StringBuilder(84);


int success = QuerySKInfo(pDataInput, pDataInput.Length, pDataOutput, 84);
if (success == -1) return null;

return new PersonalInformation(pDataOutput.ToString());
这样看看
youzelin 2009-03-03
  • 打赏
  • 举报
回复
:( 还是不行,我的代码调用大致如下:


string pDataInput = "0001";
StringBuilder pDataOutput = new StringBuilder();
int iDataOutputLen = 0;

int success = QuerySKInfo(pDataInput, 84, pDataOutput, iDataOutputLen);
if (success == -1) return null;

return new PersonalInformation(pDataOutput.ToString());


帮我看一下,调用似乎没有什么问题……,:( 不知道……,程序没有报错,直接过了,return null;
oyljerry 2009-03-03
  • 打赏
  • 举报
回复
StringBuilder 试试
zgke 2009-03-03
  • 打赏
  • 举报
回复
[DllImport(@"..\skComm.dll", EntryPoint = "QuerySKInfo")]
public static extern int QuerySKInfo(StringBuilder pInputData, int pInputLen, StringBuilder pOutputData, int pOutputLen);


这样看看 因该没问题的


icehawk 2009-03-03
  • 打赏
  • 举报
回复
StringBuilder

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧