关于C#调用c++的 dll

isreal0 2009-04-18 11:46:03
c++里有这样一个方法
void getValue(out char* c1)
也就是方法没有返回,但是通过out参数返回一个值。

在c#里我写了一个对应的方法
[DllImport(entryDll, EntryPoint = "ReadCard",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.I4)]
public unsafe static extern void getValue(out IntPtr c1);

然后,获得了传出的值 c1,再调用 string result = Marshal.IntPtrToStringAsci(c1);
但是上面这行函数居然报错了,提示写入内存错误,请问问题出在哪儿呢?
多谢了。
...全文
234 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
isreal0 2009-04-27
  • 打赏
  • 举报
回复
多谢楼上各位,其实从2楼的方法就是可行的,程序出错的关键原因是因为dll没有注册,一个注册程序跑一下就好了 - -
非常感谢各位的回帖,大家辛苦了。。。。
juqiang 2009-04-22
  • 打赏
  • 举报
回复
public unsafe static extern void getValue(out IntPtr c1);

首先,你的out的intptr需要初始化一块空间,不知道你的字符串有多大,我假设为100


IntPtr c1 = Marshal.AllocHGlobal(100+1);

// 调用你的函数
getValue(out c1);
// 得到字符串,这里可能是unicode的乱码
string tmp = Marshal.PtrToStringAuto(c1);

// 释放空间
Marshal.FreeHGlobal(c1);

// 如果是乱码,你就运行一下下面两句,否则不用了,因为不知道你的dll里面字符串怎么定义的
byte[] buf = Encoding.Unicode.GetBytes(tmp);
string ret = Encoding.Default.GetString(buf);
isreal0 2009-04-20
  • 打赏
  • 举报
回复
自己也顶下。。。
isreal0 2009-04-20
  • 打赏
  • 举报
回复
自己也顶下。。。
lybelmont 2009-04-20
  • 打赏
  • 举报
回复
哎 C#调用 C++的DLL 一直都有这样那样的问题
我也很头疼这些
一起学习 UPUP
isreal0 2009-04-20
  • 打赏
  • 举报
回复
期待高手出现。。。
oyljerry 2009-04-19
  • 打赏
  • 举报
回复
调用之前,先分配一个足够大的空间,然后再把空间地址传递进函数,函数返回后,就会修改对应的空间内容...
wonsoft 2009-04-19
  • 打赏
  • 举报
回复
2、3楼的正解。
zcandyly20211 2009-04-19
  • 打赏
  • 举报
回复
友情up!
gomoku 2009-04-19
  • 打赏
  • 举报
回复
char*是指针,out修饰符则表明该参数用来输出,输出到c1指向的缓冲区。
而C#中的out IntPtr则可以理解为传入指针的引用,用来获取一个指针,类似于C++的char**。

out char* c1,可以用来返回一个字符(可能性不大),也可以用来传入一个缓冲区,以便获得字符输出。
如果是第二种情况你可以这样写:


[DllImport(entryDll)]
public unsafe static extern void getValue(StringBuilder c1);
陌上花花 2009-04-19
  • 打赏
  • 举报
回复
帮顶下。
rtdb 2009-04-19
  • 打赏
  • 举报
回复
关键在于该方法的char* c1的内存由谁分配。
若是由外界分配,你可以试一下:
public unsafe static extern void getValue(byte[] c1);

然后new 够大的byte[]传过去。

hangang7403 2009-04-19
  • 打赏
  • 举报
回复
up
isreal0 2009-04-19
  • 打赏
  • 举报
回复
我总共做了这么几个尝试:
1 out string
2 out IntPtr
3 char[]
4 out char[]
5 StringBuilder
6 out StringBuilder
结果是,1和2在调用dll中函数时没有报错,但是在转换Marshal.PtrToStringAuto(c1); 时出错了
3456在调用dll的时候直接报了读写错误
isreal0 2009-04-19
  • 打赏
  • 举报
回复
我总共做了这么几个尝试:
1 out string
2 out IntPtr
3 char[]
4 out char[]
5 StringBuilder
6 out StringBuilder
结果是,1和2在调用dll中函数时没有报错,但是在转换Marshal.PtrToStringAuto(c1); 时出错了
3456在调用dll的时候直接报了读写错误
isreal0 2009-04-19
  • 打赏
  • 举报
回复
刚才试了2楼和3楼的方法,都不行哦,都报了读写错误。。。晕了
Garnett_KG 2009-04-19
  • 打赏
  • 举报
回复
试下AUTO


[DllImport(entryDll, EntryPoint = "ReadCard",
CharSet = CharSet.Auto, //Auto
CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.I4)]
public unsafe static extern void getValue(out IntPtr c1);

再调用 string result = Marshal.PtrToStringAuto(c1); //Auto

likegod 2009-04-19
  • 打赏
  • 举报
回复
[DllImport("Test.dll")]//Test.dll是c++文件生成的dllITPUB个人空间t0|.vh,G GdB
static extern int f_Test(byte[] pInput, String fileName);

byte[] Minput = new byte[100];

f_Test(Minput, fileName);


分配空间。
xufzu123 2009-04-19
  • 打赏
  • 举报
回复
学习~up
龙宜坡 2009-04-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 oyljerry 的回复:]
调用之前,先分配一个足够大的空间,然后再把空间地址传递进函数,函数返回后,就会修改对应的空间内容...
[/Quote]
OK!

111,126

社区成员

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

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

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