我正在尝试尝试使用Golang在Windows上加载ChakraCore.dll,但是我在弄清楚需要作为第三参数传入的参数类型时遇到困难。
我从阅读library code到松散地跟随Embedding ChakraCore的假设是,由于头文件将JsRuntimeHandle定义为{{1},因此第三个参数必须是空指针(void **) }
如果可能的话,我也希望避免使用CGo。
控制台输出:
应急:JsCreateRuntime失败:托管API的参数为null 在不允许为null的上下文中。 (JsErrorNullArgument)
代码:
typedef void *JsRuntimeHandle;
答案 0 :(得分:0)
我可能在这里出错了,但是当我只是忽略Windows给我的错误并继续前进时,一切似乎都可以正常执行。
例如,如果我运行此命令:
package main
import (
"errors"
"fmt"
"syscall"
"unsafe"
)
var (
chakraCore, _ = syscall.LoadLibrary("ChakraCore.dll")
jsCreateRuntime, _ = syscall.GetProcAddress(chakraCore, "JsCreateRuntime")
jsCreateContext, _ = syscall.GetProcAddress(chakraCore, "JsCreateContext")
jsSetCurrentContext, _ = syscall.GetProcAddress(chakraCore, "JsSetCurrentContext")
jsRunScript, _ = syscall.GetProcAddress(chakraCore, "JsRunScript")
jsConvertValueToString, _ = syscall.GetProcAddress(chakraCore, "JsConvertValueToString")
jsStringToPointer, _ = syscall.GetProcAddress(chakraCore, "JsStringToPointer")
)
const (
JsNoError = 0
JsErrorInvalidArgument = 0x10001
JsErrorNullArgument = 0x10002
JsErrorScriptCompile = 0x30002
)
const (
JsRuntimeAttributeNone = 0x00000000
)
var jsExample = `
(()=>{
return 'Hello world!';}
)()
`
func main() {
var runtime unsafe.Pointer
var context unsafe.Pointer
var jsResult unsafe.Pointer
var resultJSString unsafe.Pointer
{
const functionName = "JsCreateRuntime"
ret, _, err := syscall.Syscall(
uintptr(jsCreateRuntime),
3,
uintptr(JsRuntimeAttributeNone),
uintptr(0),
uintptr(unsafe.Pointer(&runtime)),
)
// NOTE: Skip this error as it seems to be a false positive
//if err != 0 {
// panic(fmt.Sprintf("%s invalid DLL call: %v", functionName, err))
//}
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
if runtime == nil {
panic("Runtime should not be 0. I think.")
}
fmt.Print(fmt.Sprintf("%s: runtime: %v | error code: %v | dll call error: %v\n", functionName, runtime, ret, err))
}
{
const functionName = "JsCreateContext"
ret, _, err := syscall.Syscall(
uintptr(jsCreateContext),
2,
uintptr(runtime),
uintptr(unsafe.Pointer(&context)),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: context: %v | error code: %v | dll call error: %v\n", functionName, context, ret, err))
}
{
const functionName = "JsSetCurrentContext"
ret, _, err := syscall.Syscall(
uintptr(jsSetCurrentContext),
1,
uintptr(context),
uintptr(0),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: error code: %v | dll call error: %v\n", functionName, ret, err))
}
{
const functionName = "JsRunScript"
context := 1
str, err := syscall.UTF16PtrFromString(jsExample)
if err != nil {
panic(err)
}
url, err := syscall.UTF16PtrFromString("")
if err != nil {
panic(err)
}
ret, _, err := syscall.Syscall6(
uintptr(jsRunScript),
4,
uintptr(unsafe.Pointer(str)),
uintptr(context),
uintptr(unsafe.Pointer(url)),
uintptr(unsafe.Pointer(&jsResult)),
uintptr(0),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: js result: %v | error code: %v | dll call error: %v\n", functionName, jsResult, ret, err))
}
{
const functionName = "JsConvertValueToString"
ret, _, err := syscall.Syscall(
uintptr(jsConvertValueToString),
2,
uintptr(jsResult),
uintptr(unsafe.Pointer(&resultJSString)),
uintptr(0),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
fmt.Print(fmt.Sprintf("%s: js convert val to string: %v | error code: %v | dll call error: %v\n", functionName, resultJSString, ret, err))
}
{
const functionName = "JsStringToPointer"
var utf16StringData *[0xffff]uint16
var stringLen uintptr
ret, _, err := syscall.Syscall(
uintptr(jsStringToPointer),
3,
uintptr(resultJSString),
uintptr(unsafe.Pointer(&utf16StringData)),
uintptr(unsafe.Pointer(&stringLen)),
)
if err := getJSError(ret); err != nil {
panic(fmt.Sprintf("%s failed: %s", functionName, err))
}
cStrData := syscall.UTF16ToString(utf16StringData[0 : stringLen])
fmt.Print(fmt.Sprintf("%s: js string: %s (len: %v) | error code: %v | dll call error: %v\n", functionName, cStrData, stringLen, ret, err))
}
return
}
func getJSError(errorCode uintptr) error {
switch (errorCode) {
case JsNoError:
return nil
case JsErrorInvalidArgument:
return errors.New("An argument to a hosting API was invalid. (JsErrorInvalidArgument)")
case JsErrorNullArgument:
return errors.New("An argument to a hosting API was null in a context where null is not allowed. (JsErrorNullArgument)")
case JsErrorScriptCompile:
return errors.New("JavaScript failed to compile. (JsErrorScriptCompile)")
default:
return fmt.Errorf("Unhandled error kind (%v).", errorCode)
}
}
我在控制台中得到以下输出:
JsCreateRuntime:运行时:0x3bd3310 |错误代码:0 | dll调用错误: 参数错误。
JsCreateContext:上下文:0x3ce2000 | 错误代码:0 | dll调用错误:操作成功完成。
JsSetCurrentContext:错误代码:0 | dll调用错误:操作 成功完成。
JsRunScript:js结果:0x3d00ac0 |错误 代码:0 | dll调用错误:操作成功完成。
JsConvertValueToString:js将val转换为字符串:0x3d00ac0 |错误 代码:0 | dll调用错误:操作成功完成。
JsStringToPointer:js字符串:世界您好! (len:12)|错误代码:0 | dll调用错误:操作成功完成。