从 C 访问 MATLAB 的 unicode 字符串

2023-12-02

如何通过 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'),然后从 CengEvalString(ep, "s"),然后作为输出,我从文件中获取 UTF-8 格式的文本。这证明 MATLAB 在内部将其存储为 unicode。但是如果我这样做mxArrayToString(engGetVariable(ep, "s")),我明白了什么unicode2native(s, 'Latin-1')会在 MATLAB 中给出:所有非 Latin-1 字符均替换为字符代码 26。我需要的是以任何 unicode 格式(UTF-8、UTF-16 等)以 C 字符串形式访问底层 unicode 数据,并保留非 Latin-1 字符。这可能吗?

我的平台是OS X,MATLAB R2012b。

附录:文档明确指出“[mxArrayToString()] 支持多字节编码字符”,但它仍然只给我原始数据的 Latin-1 近似值。


首先分享一些我在网上找到的参考资料:

  • 根据mxChar描述,

    MATLAB 在计算机上将字符存储为 2 字节 Unicode 字符 多字节字符集

    MBCS 这个术语还是有点模糊的对我来说,我认为他们在这种情况下意味着 UTF-16 (尽管我不确定代理对,这可能会使其成为 UCS-2)。

    UPDATE:MathWorks 将措辞更改为:

    MATLAB 对 Unicode 字符使用 16 位无符号整数字符编码。

  • The mxArrayToString页面声明它确实处理多字节编码字符(取消链接mxGetString它仅处理单字节编码方案)。不幸的是,没有关于如何执行此操作的示例。

  • 最后,这里有一个thread在 MATLAB 新闻组上,其中提到了几个与此相关的未记录函数(您可以通过加载libmx.dll库变成像这样的工具依赖步行者在 Windows 上)。


这是我在 MEX 中做的一个小实验:

my_func.c

#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!
}

我用 C 代码创建了三个字符串,分别使用 ASCII、UTF-8 和 UTF-16LE 编码。然后我使用以下命令将它们传递给 MATLABmxCreateStringMEX 函数(及其其他未记录的版本)。

我通过咨询得到了字节序列文件格式.info网站:一个 (U+0041), À (U+00C0), and 水 (U+6C34).

让我们在 MATLAB 中测试上述函数:

%# 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)

unicode_string AÀ水

我正在利用嵌入式Java功能查看字符串:

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

现在让我们反向操作(将 MATLAB 中的字符串接受到 C 中):

my_func_reverse.c

#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\n");
}

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 内部对此进行测试:

>> s = char(hex2dec(['0041';'00C0';'6C34'])');   %# "\u0041\u00C0\u6C34"
>> ss = my_func_reverse(s);
0x41 0xC3 0x80 0xE6 0xB0 0xB4 0x00               %# UTF-8 encoding
>> assert(isequal(s,ss))

最后我应该说,如果由于某种原因你仍然遇到问题, 最简单的事情是将非 ASCII 字符串转换为uint8数据类型 在将其从 MATLAB 传递到您的引擎程序之前。

所以在 MATLAB 进程内部执行以下操作:

%# 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);

并使用 Engine API 访问变量:

mxArray *arr = engGetVariable(ep, "str_bytes");
uint8_T *bytes = (uint8_T*) mxGetData(arr);
// now you decode this utf-8 string on your end ...

所有测试均在运行 R2012b 且使用默认字符集的 WinXP 上完成:

>> feature('DefaultCharacterSet')
ans =
windows-1252

希望这可以帮助..


EDIT:

在 MATLAB R2014a 中,许多无证的C 函数已从libmx库(包括上面使用的库),并替换为命名空间下公开的等效 C++ 函数matrix::detail::noninlined::mx_array_api.

调整上面的示例应该很容易(如所解释的here)在最新的 R2014a 版本上运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 C 访问 MATLAB 的 unicode 字符串 的相关文章

  • 如何找到在matlab中重复的矩阵的每一行的索引?

    我想找到矩阵中所有有重复项的行的索引 例如 A 1 2 3 4 1 2 3 4 2 3 4 5 1 2 3 4 6 5 4 3 要返回的向量将是 1 2 4 很多类似的问题建议使用unique函数 我已经尝试过 但我能得到的最接近我想要的功
  • 如何在 Matlab 中对数组应用低通或高通滤波器?

    有没有一种简单的方法可以将低通或高通滤波器应用于 MATLAB 中的数组 我对 MATLAB 的强大功能 或数学的复杂性 有点不知所措 需要一个简单的函数或一些指导 因为我无法从文档或网络搜索中找到答案 看着那 这filter http w
  • 如何在没有安装Visual Studio的另一台机器上使用Visual Studio生成的dll?

    我已经在 Visual Studio 2012 中生成了动态库 我想在另一台机器上使用该库 但我不想在远程机器上安装 Visual Studio 我有 mex 库和 dll 我想运行一个使用这两个库的脚本 当我运行脚本时 出现以下错误 缺少
  • MATLAB 教程中的 SIFT 实现

    我正在寻找 MATLAB 中的一些基本 SIFT 实现 我需要从第一原则来写它 另外 我正在寻找一些可以解释程序中发生的事情的内容 Vedali 的代码和 David Lowe 的代码超出了我的理解范围 如果您是 Matlab 用户 您一定
  • 如何在 Matlab 中将数组打印到 .txt 文件?

    我才刚刚开始学习Matlab 所以这个问题可能非常基本 我有一个变量 a 2 3 3 422 6 121 9 4 55 我希望将值输出到 txt 文件 如下所示 2 3 3 422 6 121 9 4 55 我怎样才能做到这一点 fid f
  • 在 Matlab 中将 datenum 转换为 datetime 的最快方法

    我在 Matlab 中将 datenum 转换为 datetime 时遇到问题 Given dnum floor now floor now 1 我尝试了以下方法 datenum dnum 但这没有用 我发现有效的方法是 datetime
  • 如何将任何语言和字符集的字符串转换为 Java 中的有效文件名?

    我需要根据用户输入的名称生成文件名 这些名称可以是任何语言 例如 约翰 史密斯 高岡和子 我爱你 这些是使用输入的值 因此我不能保证名称不包含文件名中无效的字符 用户将从浏览器下载这些文件 因此我需要确保文件名在所有配置的所有操作系统上都有
  • 如何更改 C++ 中存储在字符串中的文件扩展名?

    好吧 事情就是这样 我正在大学学习 C 课程 但不知道如何更改文件的扩展名 首先 我们要做的是读取 txt 文件并计算单词 句子 元音等 我明白了 但下一步是困扰我的问题 然后 我们假设使用与输入文件相同的文件名创建一个新文件 但扩展名为
  • 括号中的波形符字符

    在 MATLAB 中 以下代码执行什么操作 m func returning matrix 波浪号运算符 的作用是什么 在 Matlab 中 这意味着不要将函数中相应的输出参数分配到赋值的右侧 因此 如果func returning mat
  • matlab中类库的全局变量

    我有一些matlab声明的类 我如何声明所有类中都可见的常量 例如 这些常量可以是在所有类的方法中使用的物理常量 首先想到的是使用全局变量 还有更好的办法吗 最好在单独的文件中声明这些常量 包含常量的类是执行此操作的一种很好的干净方法 请参
  • 如何将 nvarchar 解码为文本(SQL Server 2008 R2)?

    我有一个 SQL Server 2008 R2 表nvarchar 4000 field 存储该表的数据如下所示 696D616765206D61726B65643A5472 or 303131 011 我看到每个字符都编码为十六进制 我如
  • 检测 PHP 中字符串的字符集(UTF-8 或 Windows-1256)

    我正在根据 简单的 HTML DOM http simplehtmldom sourceforge net 并且我想在获取 URL 的内部文本后检测字符串的字符集 以使用以下命令将其转换为 UTF 8 iconv 我尝试了很多东西 但没有一
  • 通过 Matlab 访问 Physionet 的 ptbdb 中的数据库

    我首先设置系统 old path which rdsamp if isempty old path rmpath old path 1 end 8 end wfdb url http physionet org physiotools ma
  • python 和 android 中通过 AES 算法加密和解密

    我有用于 AES 加密的 python 和 android 代码 当我在android中加密文本时 它在python上成功解密 但无法在android端解密 有人有想法吗 Python代码 import base64 import hash
  • 如何在文本集中创建所有字符组合?

    例如 我有这样的文本集 第 1 栏 a b 第 2 栏 l m n 第 3 栏 v w x y 我想将它们组合起来以获得如下输出 alv alw alx aly amv amw amx amy 这将输出 24 种文本组合 如果我只使用前两列
  • 有效地绘制大时间序列(matplotlib)

    我正在尝试使用 matplotlib 在同一轴上绘制三个时间序列 每个时间序列有 10 6 个数据点 虽然生成图形没有问题 但 PDF 输出很大 在查看器中打开速度非常慢 除了以栅格化格式工作或仅绘制时间序列的子集之外 还有其他方法可以获得
  • 了解 fminunc 参数和匿名函数、函数处理程序

    请多多包涵 问题在最后 我试图找出 fminunc 调用方式的差异 这个问题源于 Andrew Ng 在他的 Coursera 机器学习课程中的第 3 周材料 我正在回答这个问题 Matlab Andrew Ng 机器学习课程中 t cos
  • 如何在 Sublime Text 中查看文件的当前编码?

    如何在 Sublime Text 中查看文件的当前编码 这看起来是一件很简单的事情 但搜索并没有取得太多成果 任何指示将不胜感激 由于该线程是谷歌搜索中的热门结果 因此以下是 Sublime Text 3 build 3059 的方法 在用
  • MATLAB 中的霍夫变换

    有谁知道如何使用霍夫变换来检测二值图像中最强的线 A zeros 7 7 A 6 10 18 24 36 38 41 1 使用 rho theta 格式 其中 theta 以 45 为步长 从 45 到 90 以及如何在 MATLAB 中显
  • 图像处理 - 使用 opencv 进行服装分割

    我正在使用 opencv 进行服装特征识别 第一步 我需要通过从图像中移除脸部和手来分割 T 恤 任何建议表示赞赏 我建议采用以下方法 Use 阿德里安 罗斯布鲁克的用于检测皮肤的皮肤检测算法 谢谢罗莎 格隆奇以获得他的评论 在方差图上使用

随机推荐