js-v8添加对Windows-Api支持 - (1)v8编译调用和基本方法
v8 是以前从github下载, 版本比较老, 编译器用vs2010
用vs2010编译需要改比较多东西, 另外还需要Python, 我用的是Python2.7
v8在代码中引用如下
#define V8_TARGET_ARCH_IA32 1
#define ENABLE_DEBUGGER_SUPPORT 1
#include "../../V8/src/v8.h"
#include "../../V8/src/debug.h"
v8初始化
BOOL CJavaScriptV8::Init()
{
HandleScope handle_scope;
if(m_bInit)
return TRUE;
m_bInit = TRUE;
m_global = ObjectTemplate::New();
m_global->Set(String::New("dbg_output"), FunctionTemplate::New(dbg_output));
OnInitGlobal();
m_context = Context::New(NULL, m_global);
m_context_scope = new Context::Scope(m_context);
return TRUE;
}
v8执行脚本
BOOL CJavaScriptV8::LoadCode(CHAR *pCode, CHAR *pFileName, string *pReult)
{
BOOL bRetVal;
if(pReult)
pReult->clear();
bRetVal = Init();
if(bRetVal == FALSE)
return FALSE;
HandleScope handle_scope;
TryCatch try_catch;
Handle<Script> script;
Handle<String> source;
Handle<Value> name;
Handle<Value> result;
CHAR *pText;
string sInfo;
if(pFileName == NULL)
pFileName = "(NoName)";
// InitDebug();
m_sError = "";
source = String::New(pCode);
name = String::New(pFileName);
script = Script::Compile(source, name);
if(script.IsEmpty())
{
GetFailInfo(try_catch, sInfo);
m_sError = sInfo;
m_bError = TRUE;
return FALSE;
}
result = script->Run();
if(result.IsEmpty())
{
GetFailInfo(try_catch, sInfo);
m_sError = sInfo;
m_bError = TRUE;
return FALSE;
}
if(result->IsUndefined())
return TRUE;
String::Utf8Value str(result);
pText = *str ? *str : "(null)";
ATLTRACE("LoadCode: %s\r\n", pText);
if(pReult)
pReult->assign(pText);
return TRUE;
}
v8调用js函数
BOOL CJavaScriptV8::FunCall(CHAR *pFunName, string &sIn, string &sResult)
{
HandleScope handle_scope;
Local<Object> Global;
Handle<String> Fun_name, InStr;
Handle<Value> FunVal, Arg, Result;
Handle<Function> Fun;
string sUtf8;
Global = (*m_context)->Global();
Fun_name = String::New(pFunName);
FunVal = Global->Get(Fun_name);
if(FunVal->IsFunction() == false)
{
ATLTRACE("FunCall Fun miss: %s\r\n", pFunName);
return FALSE;
}
Fun = Handle<Function>::Cast(FunVal);
InStr = String::New(sIn.c_str());
Arg = InStr;
Result = Fun->Call(Global, 1, &Arg);
String::Utf8Value str(Result);
sResult = *str ? *str : "(null)";
return TRUE;
}
v8接口调试信息
var console = (typeof(console) == "undefined") ?
{
log: dbg_output,
error: dbg_output,
warn: dbg_output,
info: dbg_output,
} : console;
Handle<Value> dbg_output(const Arguments& args)
{
Handle<Value> value, result;
string sText, sAcp;
int i, nRetVal, argc;
argc = args.Length();
if((argc == 1) && (args[0]->IsObject()))
{
value = args[0];
g_pJsV8->ObjGetText(*value, sText);
nRetVal = g_pJsV8->OnDbgOutput(sText.data());
result = Integer::New(nRetVal);
return result;
}
for(i=0; i<argc; i++)
{
String::Utf8Value text_u8(args[i]);
if(i)
sText += ",";
sText += (char *)*text_u8;
}
NStr::CodePageConvert(CP_UTF8, CP_ACP, (CHAR *)sText.c_str(), sAcp);
nRetVal = g_pJsV8->OnDbgOutput(sText.data());
result = Integer::New(nRetVal);
return result;
}
基本用法示例如上, 对api支持创建对象
var wapi = (typeof(wapi) == "undefined") ?
{
_get : wapi__get,
test: wapi_test,
call: wapi_call,
alloc: wapi_alloc,
totext: wapi_totext,
toint32: wapi_toint32,
buf_read: wapi_buf_read,
buf_write: wapi_buf_write,
callback_new: wapi_callback_new,
callback_del: wapi_callback_del,
} : wapi;
调用api核心为 wapi_call 函数
Handle<Value> wapi_call(const Arguments& args)
{
Handle<Value> value, result;
string sText[64];
int arg_list[64];
int i, nArgc, nRetVal;
CHAR *pApiName;
BOOL bRetVal;
CHAR szText[1024];
value = args[0];
if(value->IsString() == FALSE)
{
sprintf(szText, "wapi_call name type error");
result = ThrowException(String::New(szText));
return result;
}
String::Utf8Value name(value);
pApiName = *name;
nArgc = args.Length();
nArgc = min(nArgc, 64) - 1;
for(i=0; i<nArgc; i++)
{
value = args[i+1];
bRetVal = ParseArg(value, arg_list[i], sText[i]);
if(bRetVal == FALSE)
{
sprintf(szText, "wapi_call bad type parameters: %d", i+2);
result = ThrowException(String::New(szText));
return result;
}
}
bRetVal = ApiCall(pApiName, arg_list, nArgc, nRetVal);
if(bRetVal == FALSE)
{
result = ThrowException(String::New("wapi_call call error"));
}
result = Integer::New(nRetVal);
return result;
}
BOOL ParseArg(Handle<Value> value, int &nValue, string &sText)
{
Local<Int32> int_val;
CHAR *pText;
int nBufCount;
BOOL bRetVal;
if(value->IsString())
{
bRetVal = GetBufByString(*value, &pText, &nBufCount);
if(bRetVal)
{
nValue = (int)pText;
return TRUE;
}
String::Utf8Value sU8(value);
pText = *sU8;
NStr::CodePageConvert(CP_UTF8, CP_ACP, pText, sText);
nValue = (int)sText.data();
return TRUE;
}
if(value->IsInt32())
{
int_val = value->ToInt32();
nValue = int_val->Value();
return TRUE;
}
return FALSE;
}
BOOL GetBufByString(Value *value, CHAR **ppText, int *pSize)
{
internal::Handle<internal::String> istr;
internal::SeqAsciiString *astr;
Handle<String> str;
char *pText;
int nSize;
if(value->IsString() == false)
return FALSE;
str = value->ToString();
istr = Utils::OpenHandle(*str);
if(istr->IsSeqAsciiString() == FALSE)
return FALSE;
astr = internal::SeqAsciiString::cast(*istr);
pText = astr->GetChars();
nSize = istr->length();
nSize = astr->length();
*ppText = pText;
*pSize = nSize;
return TRUE;
}
调用api的js示例
wapi.call("MessageBoxA", hwnd, "翻跟斗风格和地方", "sdfsdg", 16);
调用api主要点
- api的名称转换从函数可以从系统dll用GetProcAddress获取
- 参数转换主要是字符串过程参考上面的ParseArg
- 函数调用可以内嵌汇编代码去调用
另外内存相关的后续说明
v8相关一些问题
- Handle
为外部使用的对象, internal::Handleinternal::String这种才是js引擎中实际的对象, 不同种类生存周期是不一样的 - js中的字符串实际是有很多种的, 最基本简单的是 SeqAsciiString, 复杂的带中文的使用的是utf方式, 需要用String::Utf8Value
- 创建对象可以用Integer::New, String::New等
- js中的对象没有办法直接获取类型, 类似代码如下
internal::InstanceType GetValueType(Value *value)
{
internal::Handle<internal::Object> iobj;
internal::HeapObject *phboj;
internal::Map *pmap;
internal::InstanceType nType;
iobj = Utils::OpenHandle(value);
if(iobj->IsHeapObject())
{
phboj = internal::HeapObject::cast(*iobj);
pmap = phboj->map();
nType = pmap->instance_type();
}
else
{
if(iobj->IsSmi())
nType = internal::SMI_TYPE;
else if(iobj->IsNumber())
nType = internal::JS_VALUE_TYPE;
else
nType = internal::INVALID_TYPE;
}
return nType;
}

浙公网安备 33010602011771号