0

我正在尝试让 ChakraCore.dll 使用 Golang 在 Windows 上加载,但我无法确定需要作为第三个参数传入的参数类型。

我从阅读库代码并松散地遵循Embedding ChakraCore的假设是,第三个参数需要是一个 void 指针指针(void**),因为头文件将 JsRuntimeHandle 定义为typedef void *JsRuntimeHandle;

如果可能的话,我希望避免使用 CGo。

控制台输出:

恐慌:JsCreateRuntime 失败:在不允许 null 的上下文中,托管 API 的参数为 null。(JsErrorNullArgument)

代码:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

var (
    chakraCore, _        = syscall.LoadLibrary("ChakraCore.dll")
    jsCreateRuntime, _ = syscall.GetProcAddress(chakraCore, "JsCreateRuntime")
)

const (
    JsNoError = 0
    JsErrorNullArgument = 0x10002
)

const (
    JsRuntimeAttributeNone = 0x00000000
)

func main() {
    const functionName = "JsCreateRuntime"
    var runtime uintptr
    ret, _, err := syscall.Syscall(
       uintptr(jsCreateRuntime),
       3,
       uintptr(JsRuntimeAttributeNone),
       uintptr(0),
       uintptr(unsafe.Pointer(runtime)),
    )
    if err != 0 {
        panic(fmt.Sprintf("%s failed: %v", functionName, err))
    }
    switch (ret) {
    case JsNoError:
        break
    case JsErrorNullArgument:
        panic(fmt.Sprintf("%s failed: An argument to a hosting API was null in a context where null is not allowed. (JsErrorNullArgument)", functionName))
    default:
        panic(fmt.Sprintf("%s failed: Unhandled error kind (%v).", functionName, ret))
    }
    panic(fmt.Sprintf("runtime: %v | ret: %v\n", runtime, uint(ret)))
    return
}
4

1 回答 1

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字符串:世界你好!(长度:12)| 错误代码:0 | dll调用错误:操作成功完成。

于 2019-06-02T06:03:42.647 回答