Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

从v8到C++的数据类型转换

  这里说的数据类型指的是基本数据类型(数值、字符、布尔),对象类型实际上也只是基本类型的结构化堆叠而已,对于数据类型的转换我们只要考虑基本类型就够了。而在V8中所有数据类型都继承于Value类的,我们只要知道Value实例如何转换成C++基本类型即可。
  Value类的成员函数中直接就提供了数值型和布尔型的转换函数,直接调用它就可以得到相应的值。但是对于字符串就麻烦了,由于有编码问题,没有在Value的成员函数中封装,而是在String的静态成员下添加了几个类成员来实现字符串的转换。
  首先看Value类,里面提供了一大堆的方法,不过基本都是判断类型和内部装换用的。但其中也有几个外部转换的方法:
    bool BooleanValue()
    double NumberValue()
    int32_t Int32Value()
    int64_t IntegerValue()
    uint32_t Uint32Value()
  在Value实例上直接调用这些方法就可以得到相应的C++基本类型。对于字符串,我们再看看String类下面用于抽出数据的静态类:
    class String::AsciiValue()
    class String::Utf8Value()
    class String::Value()
  从名字就可以大概看出他们的功能。AsciiValue是直接使用ASCII字符,这意味着遇到多字节字符时候只取第一个字节,后面的抛弃。Utf8Value是把字符串以UTF-8的字符集导出,字母占一个字节,汉字占三个字节。最后一个Value是使用Unicode导出数据,字母和汉字都占两个字节。这东西测试起来有点麻烦了,因为控制台输出字符串的默认编码是ANSI,以上三种编码方式抽取的数据直接输出到控制台都无法显示汉字。所以我在后面的测试中不直接输出字符串,而是把他们的字节逐个输出来。
  然而,这三个东西是类啊,又不是函数,就算创建了这些类的实例又要怎么转换成C++的字符串格式呢?实际上这三个类的实例的数据部分就是一个字符串指针,已经没有多余的数据了,我们只要取出它指向的字符串即可。注意这里的字符串指针(string*),而不是字符指针(char*)。所以使用“*”运算符来取它们的目标对象才会得到一个字符串(string)。或者说它原本是指向字符指针的指针(char**),使用“*”运算符把它还原成字符指针(char*)。
  下面是代码:
//\node_modules\test.cpp
#include <node.h>
#include <iostream>
#pragma comment(lib,"node.lib")
using namespace v8;
using namespace std;

Handle<Value> f(const Arguments &args){
  //双精度浮点数
  cout<<args[0]->NumberValue()<<endl;
  //64位整数
  cout<<args[0]->IntegerValue()<<endl;
  //32位整数
  cout<<args[0]->Int32Value()<<endl;
  //32位无符号整数
  cout<<args[0]->Uint32Value()<<endl;
  //布尔
  cout<<args[2]->BooleanValue()<<endl;
  //UTF-8字符串
  String::Utf8Value s1(args[1]);
  byte *v1=(byte*)*s1;
  cout<<(int)v1[0]<<" "<<(int)v1[1]<<" "<<(int)v1[2]<<endl;
  //ASCII字符串
  String::AsciiValue s2(args[1]);
  byte *v2=(byte*)*s2;
  cout<<(int)v2[0]<<endl;
  //Unicode字符串
  String::Value s3(args[1]);
  byte *v3=(byte*)*s3;
  cout<<(int)v3[0]<<" "<<(int)v3[1]<<" "<<endl;
  //该函数返回一个undefined
  return Undefined();
};

void main(Handle<Object> exports){
  //把C++中的函数f做成JavaScript函数
  auto js_f=FunctionTemplate::New(f)->GetFunction();
  //把刚做成的函数赋到模块接口对象的f属性上
  exports->Set(String::NewSymbol("f"),js_f);
}

NODE_MODULE(test,main)
//\test.njs
var test=require('test');
console.log(test.f(3,"钴",true));
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^