【问题标题】:How do I pass a void pointer pointer to a Windows DLL in Golang (void**)如何将 void 指针传递给 Golang 中的 Windows DLL (void**)
【发布时间】:2019-05-23 09:51:46
【问题描述】:

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

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

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

控制台输出:

恐慌:JsCreateRuntime 失败:托管 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
}

【问题讨论】:

    标签: windows go chakra chakracore


    【解决方案1】:

    我可能在这里出错了,但是当我忽略 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调用错误:操作成功完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 2018-08-27
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多