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主要点

  1. api的名称转换从函数可以从系统dll用GetProcAddress获取
  2. 参数转换主要是字符串过程参考上面的ParseArg
  3. 函数调用可以内嵌汇编代码去调用
    另外内存相关的后续说明

v8相关一些问题

  1. Handle为外部使用的对象, internal::Handleinternal::String这种才是js引擎中实际的对象, 不同种类生存周期是不一样的
  2. js中的字符串实际是有很多种的, 最基本简单的是 SeqAsciiString, 复杂的带中文的使用的是utf方式, 需要用String::Utf8Value
  3. 创建对象可以用Integer::New, String::New等
  4. 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;
}
posted @ 2022-06-02 11:56  Yofoo  阅读(428)  评论(0)    收藏  举报