我正在尝试使用 Golang 在 Windows 上加载 ChakraCore.dll,但我无法弄清楚我需要将什么参数类型作为第三个参数传递。
我阅读 library code 的假设并松散地遵循 Embedding ChakraCore是第三个参数需要是空指针指针 (void**),因为头文件将 JsRuntimeHandle 定义为 typedef void *JsRuntimeHandle;
如果可能的话,我也希望避免使用 CGo。
控制台输出:
panic: JsCreateRuntime failed: An argument to a hosting API was null in a context where null is not allowed. (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 给我的错误并继续前进时,一切似乎都执行得很好。
例如,如果我运行这个:
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: runtime: 0x3bd3310 | error code: 0 | dll call error: The parameter is incorrect.
JsCreateContext: context: 0x3ce2000 | error code: 0 | dll call error: The operation completed successfully.
JsSetCurrentContext: error code: 0 | dll call error: The operation completed successfully.
JsRunScript: js result: 0x3d00ac0 | error code: 0 | dll call error: The operation completed successfully.
JsConvertValueToString: js convert val to string: 0x3d00ac0 | error code: 0 | dll call error: The operation completed successfully.
JsStringToPointer: js string: Hello world! (len: 12) | error code: 0 | dll call error: The operation completed successfully.
关于windows - 如何在 Golang 中将 void 指针传递给 Windows DLL (void**),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56272558/