从C访问MATLAB的unicode字符串
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从C访问MATLAB的unicode字符串相关的知识,希望对你有一定的参考价值。
如何通过MATLAB Engine或MEX C接口访问MATLAB字符串的基础unicode数据?
这是一个例子。我们将unicode字符放在UTF-8编码文件test.txt中,然后将其读作
fid=fopen('test.txt','r','l','UTF-8');
s=fscanf(fid, '%s')
在MATLAB中。
现在,如果我首先做feature('DefaultCharacterSet', 'UTF-8')
,然后从C engEvalString(ep, "s")
,然后作为输出我从文件中取回文件为UTF-8。这证明MATLAB在内部将其存储为unicode。但是,如果我做mxArrayToString(engGetVariable(ep, "s"))
,我得到unicode2native(s, 'Latin-1')
会在MATLAB中给我的东西:所有非拉丁字符1字符都替换为字符代码26.我需要的是以任何unicode格式(UTF)访问底层unicode数据作为C字符串-8,UTF-16等),并保留非Latin-1字符。这可能吗?
我的平台是OS X,MATLAB R2012b。
附录:documentation明确声明“[mxArrayToString()]支持多字节编码字符”,但它仍然只给出了原始数据的Latin-1近似值。
首先,让我分享一下我在网上找到的一些参考文献:
- 根据
mxChar
的描述, MATLAB将字符存储为具有多字节字符集的机器上的2字节Unicode字符 MBCS对我来说仍然有点ambiguous,我认为它们在这种情况下意味着UTF-16(虽然我不确定surrogate pairs,它可能使它成为UCS-2)。 更新:MathWorks将措辞改为: MATLAB对Unicode字符使用16位无符号整数字符编码。 - qazxsw poi页面声明它确实处理多字节编码字符(取消链接qazxsw poi,它只处理单字节编码方案)。不幸的是,没有关于如何做到这一点的例子。
- 最后,这里有一个关于MATLAB新闻组的
mxArrayToString
,它提到了几个与此无关的未记录的函数(你可以通过将mxGetString
库加载到像Windows上的Dependency Walker这样的工具来自己找到它们)。
这是我在MEX中做的一个小实验:
my_func.c
thread
我在C代码中创建三个字符串,分别用ASCII,UTF-8和UTF-16LE编码。然后我使用libmx.dll
MEX函数(以及其他未记录的版本)将它们传递给MATLAB。
我通过咨询Fileformat.info网站得到了字节序列:#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char str_ascii[] = {0x41, 0x6D, 0x72, 0x6F, 0x00}; // {'A','m','r','o',0}
char str_utf8[] = {
0x41, // U+0041
0xC3, 0x80, // U+00C0
0xE6, 0xB0, 0xB4, // U+6C34
0x00
};
char str_utf16_le[] = {
0x41, 0x00, // U+0041
0xC0, 0x00, // U+00C0
0x34, 0x6C, // U+6C34
0x00, 0x00
};
plhs[0] = mxCreateString(str_ascii);
plhs[1] = mxCreateString_UTF8(str_utf8); // undocumented!
plhs[2] = mxCreateString_UTF16(str_utf16_le); // undocumented!
}
,mxCreateString
和A (U+0041)。
让我们在MATLAB中测试上面的函数:
À (U+00C0)
我正在利用水 (U+6C34)来查看字符串:
%# call the MEX function
[str_ascii, str_utf8, str_utf16_le] = my_func()
%# MATLAB exposes the two strings in a decoded form (Unicode code points)
double(str_utf8) %# decimal form: [65, 192, 27700]
assert(isequal(str_utf8, str_utf16_le))
%# convert them to bytes (in HEX)
b1 = unicode2native(str_utf8, 'UTF-8')
b2 = unicode2native(str_utf16_le, 'UTF-16')
cellstr(dec2hex(b1))' %# {'41','C3','80','E6','B0','B4'}
cellstr(dec2hex(b2))' %# {'FF','FE','41','00','C0','00','34','6C'}
%# (note that first two bytes are BOM markers)
%# show string
view_unicode_string(str_utf8)
现在让我们反向工作(接受MATLAB中的字符串到C):
my_func_reverse.c
embedded Java capability
我们从MATLAB内部测试这个:
function view_unicode_string(str)
%# create Swing JLabel
jlabel = javaObjectEDT('javax.swing.JLabel', str);
font = java.awt.Font('Arial Unicode MS', java.awt.Font.PLAIN, 72);
jlabel.setFont(font);
jlabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
%# place Java component inside a MATLAB figure
hfig = figure('Menubar','none');
[~,jlabelHG] = javacomponent(jlabel, [], hfig);
set(jlabelHG, 'Units','normalized', 'Position',[0 0 1 1])
end
最后我应该说,如果由于某种原因你仍然遇到问题,最简单的方法是将非ASCII字符串转换为#include "mex.h"
void print_hex(const unsigned char* s, size_t len)
{
size_t i;
for(i=0; i<len; ++i) {
mexPrintf("0x%02X ", s[i] & 0xFF);
}
mexPrintf("0x00
");
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char *str;
if (nrhs<1 || !mxIsChar(prhs[0])) {
mexErrMsgIdAndTxt("mex:error", "Expecting a string");
}
str = mxArrayToString_UTF8(prhs[0]); // get UTF-8 encoded string from Unicode
print_hex(str, strlen(str)); // print bytes
plhs[0] = mxCreateString_UTF8(str); // create Unicode string from UTF-8
mxFree(str);
}
数据类型,然后再将其从MATLAB传递到引擎程序。
所以在MATLAB过程中做:
>> s = char(hex2dec(['0041';'00C0';'6C34'])'); %# "u0041u00C0u6C34"
>> ss = my_func_reverse(s);
0x41 0xC3 0x80 0xE6 0xB0 0xB4 0x00 %# UTF-8 encoding
>> assert(isequal(s,ss))
并使用Engine API访问变量:
uint8
所有测试都是在运行R2012b的WinXP上使用默认字符集完成的:
%# read contents of a UTF-8 file
fid = fopen('test.txt', 'rb', 'native', 'UTF-8');
str = fread(fid, '*char')';
fclose(fid);
str_bytes = unicode2native(str,'UTF-8'); %# convert to bytes
%# or simply read the file contents as bytes to begin with
%fid = fopen('test.txt', 'rb');
%str_bytes = fread(fid, '*uint8')';
%fclose(fid);
希望这可以帮助..
编辑:
在MATLAB R2014a中,许多未记录的C函数从mxArray *arr = engGetVariable(ep, "str_bytes");
uint8_T *bytes = (uint8_T*) mxGetData(arr);
// now you decode this utf-8 string on your end ...
库中删除(包括上面使用的函数),并替换为在命名空间>> feature('DefaultCharacterSet')
ans =
windows-1252
下公开的等效C ++函数。
应该很容易调整上面的示例(如libmx
所解释的)以在最新的R2014a版本上运行。
以上是关于从C访问MATLAB的unicode字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何在MATLAB中将原始Unicode十六进制转换为Unicode表示
如何从 UTF-8 字符串的每个字符中获取 UNICODE 代码?