如何在Golang(void **)中将空指针指针传递给Windows DLL

时间:2019-05-23 09:51:47

标签: windows go chakra chakracore

我正在尝试尝试使用Golang在Windows上加载ChakraCore.dll,但是我在弄清楚需要作为第三参数传入的参数类型时遇到困难。

我从阅读library code到松散地跟随Embedding ChakraCore的假设是,由于头文件将JsRuntimeHandle定义为{{1},因此第三个参数必须是空指针(void **) }

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

控制台输出:

  

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

代码:

typedef void *JsRuntimeHandle;

1 个答案:

答案 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调用错误:操作成功完成。