作者tw30912 (tw30912)
看板C_Sharp
标题[问题] 丢阵列中文字串给c++ dll 长度异常
时间Sat May 9 15:00:33 2020
我的程式很简单
用 c# 引用 c++ 的 dll
c++ dll 的内容如下:
extern "C" _declspec(dllexport) void func1(char* inputStr)
{
return;
}
extern "C" _declspec(dllexport) void func2(char* inputStrArr[])
{
char* inputStr0 = inputStrArr[0];
char* inputStr1 = inputStrArr[1];
return;
}
c# 端的内容如下:
class Program
{
[DllImport("CPP.dll")]
public static extern void func1(string inputStr);
[DllImport("CPP.dll")]
public static extern void func2(string [] inputStrArr);
static void Main(string[] args)
{
string s0 = "中文chinese";
string s1 = "嗨123";
func1(s0);
func1(s1);
string[] strArr = new string[2];
strArr[0] = s0;
strArr[1] = s1;
func2(strArr);
}
}
说明:
我有2个函数 func1 可以传入单一字串,
func2 则可传多个字串, 以字串阵列的方式传给 c++
现在, 我有2个字串, s0 和 s1. 都含中文字符
首先, call func1 两次, 分别传入 s0 和 s1 自 c++ 端
c++ 端看到的字串内容正确, 字尾没有少算.
接着, call func2 , 把 s0 和 s1 包成 strArr 传入 c++ 端
在传入前, 有在 c# 端检查 strArr, 字串内容正确
但是传入 c++端後, 字串内容异常
inputStr0 = "中文chine"
inputStr1 = "嗨12"
我一直搞不懂的地方是,
为什麽用 func1 的时候,
c++ 端看到的中文字串长度不会被少算???
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.163.216.67 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1589007635.A.358.html
1F:推 OppOops: 因为 compiler 大概有帮你 Marshal 做好 05/09 16:02
2F:→ OppOops: c# string 用的是 UTF-16, 对应 c++ 要用 wchar_t 05/09 16:03
3F:→ OppOops: 或是 LPWSTR 05/09 16:04
4F:→ OppOops: 另外 char* 要判断长度得在字尾加上 '\0' 05/09 16:06
5F:→ OppOops: 是 string[] 的话大概 runtime 也没帮你加上吧 05/09 16:07
6F:→ OppOops: 或是直接当作是 ansi 来做长度判断了 05/09 16:07
7F:→ OppOops: 要转型过去请自己 Marshal 好, 或是一律转长宽字元 05/09 16:10
感谢你的回答,
关於 func1的问题, 我查了一下字串的预设封送处理
如果没有写 MarshalAs. 则默认值为 UnmanagedType.LPStr
其描述为“ANSI 字元之 Null 终端阵列的指标”
我的理解是, 他会把 c# 字串以 ANSI 解读, 并找到字尾符号,
我的 c++ 端用 char* 接收, 恰好没问题
不过, func2 也没写 MarshalAs
在 c++ 端得到的字串, 我用 memory 去看长这样
inputStr0 = 中文chine.e
inputStr1 = 嗨12.
其中 . 代表句尾符号
我在想他是不是像 func1 一样, array 中每个 string 都
被默认当成 ANSI 解读, 且无遗漏复制给 c++
只是他会多做一件事, 在 c# string 原始长度的下一个位置改成字尾符号
例如, 原本 "中文chinese" 在 c# 长度为 9
可是他用 ANSI 解读需要长度 11 才能描述
所以 c++ 的 char* 用长度 11 去装他
但是在 c# string 原始长度 9 的下一个位置 10 会被改成字尾符号
所以 c++ 的 memory 才会看到 "中文chine.e"
不知道是不是这样解释?
另外, 确实写好 MarshalAs 且 c++ 用 wchar 去接, 就没问题.
※ 编辑: tw30912 (1.163.216.67 台湾), 05/09/2020 18:20:09
8F:推 OppOops: 大致上没有错 基本上我会使用清楚的写法 05/09 19:02
9F:→ OppOops: 依靠 compiler 预设行为的语法我会尽量避免 05/09 19:02
10F:→ OppOops: Unmanaged / managed code 的转换很多得靠自己 05/09 19:04
11F:→ OppOops: 不然程式怎麽 crash 都不知道, 会很惨烈.. 05/09 19:05