2

我正在为DAB 开发板编写 Node.js 前端,最终将在 Raspberry Pi 上运行。我是一名 Java 和 Web 开发人员,我正在努力使用 C++ 并在不同类型的字符串之间进行转换。

DAB 板带有一个 C++ SDK,具有许多方便的功能。它允许我使用GetTotalProgram(). 对于我可以调用GetProgramName以获取程序名称的每个程序:

GetProgramName(char mode, long dabIndex, char namemode, wchar_t * programName)

... 其中mode表示FMor DABnamemode表示长名或短名。该程序的名称将在 中返回programName

为了将 转换wchar_t *programNamev8::String,我找到了我正在使用的这个片段,并了解以下基础知识:

  wchar_t buff[300];
  char cbuff[600];
  GetProgramName(0, i, 1, buff);
  wcstombs( cbuff, buff, wcslen(buff) );
  Local<String> str = String::NewFromUtf8(isolate, (const char *) cbuff, v8::String::kNormalString, wcslen(buff));

我遍历可用的程序并建立一个v8::Array

void GetPrograms(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  wchar_t buff[300];
  char cbuff[600];
  int numberOfPrograms, i;

  numberOfPrograms = GetTotalProgram();
  Local<v8::Array> ARRAY = Array::New(isolate, totalprogram);

  for (i = 0; i < numberOfPrograms; i++) {
    if (GetProgramName(0, i, 1, buff)) {
      wcstombs( cbuff, buff, wcslen(buff) );
      Local<String> str = String::NewFromUtf8(isolate, (const char *) cbuff, v8::String::kNormalString, wcslen(buff));
      Local<Object> obj = Object::New(isolate);
      obj->Set(String::NewFromUtf8(isolate, "name"), str);
      ARRAY->Set(i, obj);
    }
  }
  args.GetReturnValue().Set(ARRAY);
}

我从我的 Node 应用程序中调用 C++ 方法:

var programs = ext.getPrograms();
for (var i = 0; i < programs.length; i++) {
  console.log(programs[i][name]);
}

这主要是可行的,但是当程序的名称包含非 ASCII 字符时,例如Æ, Ø, Å,ARRAY 中的下一个元素有一个 borked name

console.log与预期输出相比,这是 Node 片段实际输出 ( ) 的内容:

| ACTUAL    | EXPECTED   |
| --------- | ---------- |
| NRK SUPER | NRK SUPER  |
| NRK VUPER | NRK VÆR    |
| NRK P1 ER | NRK P1     |

似乎非 ASCII 字符会导致下一个wcstombs提前退出,而不是复制后面的字符。

为什么会这样?有没有更好的方法来创建v8::String我的wchar_t

注意: 我现在已经能够将此问题隔离到wcstombs在 Raspberry Pi 上运行时的方法。以下代码:

#include <stdio.h>
#include <string>
#include <cstring>
#include <cstdlib>

char cbuff[600];
wchar_t buff[300] = L"ABCø123abc";

int main( int argc, const char* argv[] ) {
    wcstombs( cbuff, buff, wcslen(buff) );
    wprintf(L"wcslen of wchar_t array: %u - strlen of char array: %u\n", (char) wcslen(buff), strlen(cbuff));
}

在 Mac 上运行时,输出
wcslen of wchar_t array: 10 - strlen of char array: 10
但在 Raspberry 上运行时,输出
wcslen of wchar_t array: 10 - strlen of char array: 3- 也就是说,它只计算字符之前的ø字符

这看起来类似于这个未回答的问题

4

3 回答 3

3
WCHAR str[256];0
... // fill str array here
Local<String> v8str = String::NewFromTwoByte(isolate, (const uint16_t *) str);

注意::NewFromTwoByte用法而不是::NewFromUtf8and (const uint16_t *)cast。

::NewFromTwoByte从 UTF-16 数据分配一个新字符串。

于 2016-11-07T09:30:10.313 回答
0

问题出在wcstombs( cbuff, buff, wcslen(buff) )调用中,它会在遇到非 ASCII 字符时停止复制字符。文档说此函数的行为取决于所选 C 语言环境的 LC_CTYPE 类别。

所以将语言环境设置为 UTF-8 变体解决了这个问题:

setlocale(LC_CTYPE, "C.UTF-8");

完成此操作后,我现在可以v8::String这样创建 s:

wchar_t buff[300] = L"Something non-ASCII ÆØÅ here";
char cbuff[600];
wcstombs( cbuff, buff, wcslen(buff) );
Local<String> str = String::NewFromUtf8(isolate, (const char *) cbuff, v8::String::kNormalString, wcslen(buff));
于 2015-08-19T16:31:48.747 回答
0

我猜 wcstombs 中的最后一个参数是问题的原因。而不是尝试

 wcstombs( cbuff, buff, wcslen(buff) );

尝试

memset(cbuff, 0, sizeof(cbuff));
wcstombs( cbuff, buff, sizeof(cbuff) );
于 2015-08-18T11:55:42.180 回答