gpt4 book ai didi

go - 从 Tcl 脚本调用 golang 函数

转载 作者:数据小太阳 更新时间:2023-10-29 03:40:26 25 4
gpt4 key购买 nike

我们使用第三方 Tcl 解析库来验证 Tcl 脚本的语法和语义检查。驱动程序是用 C 语言编写的,并定义了一组实用函数。然后它调用 Tcl_CreateObjCommand 因此脚本可以调用这些 C 函数。现在我们正在将主程序移植到 go 中,但我找不到执行此操作的方法。有人知道从 Tcl 脚本调用 golang 函数的方法吗?

static int
create_utility_tcl_cmds(Tcl_Interp* interp)
{
if (Tcl_CreateObjCommand(interp, "ip_v4_address",
ip_address, (ClientData)AF_INET, NULL) == NULL) {
TCL_CHECKER_TCL_CMD_EVENT(0, "ip_v4_address");
return -1;
}

.....
return 0;
}

最佳答案

假设您已将相关函数设置为已导出并构建项目的 Go 部分

Using Go code in an existing C project

[…]

The important things to note are:

  • The package needs to be called main
  • You need to have a main function, although it can be empty.
  • You need to import the package C
  • You need special //export comments to mark the functions you want callable from C.

I can compile it as a C callable static library with the following command:

go build -buildmode=c-archive foo.go

那么剩下要做的核心工作就是将 Tcl 的 API 中的 C 粘合函数写入您的 Go 代码。这将涉及类似以下的功能:

static int ip_address_glue(
ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
// Need an explicit cast; ClientData is really void*
GoInt address_family = (GoInt) clientData;

// Check for the right number of arguments
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "address");
return TCL_ERROR;
}

// Convert the argument to a Go string
GoString address;
int len;
address.p = Tcl_GetStringFromObj(objv[1], &len);
address.n = len; // This bit is hiding a type mismatch

// Do the call; I assume your Go function is called ip_address
ip_address(address_family, address);

// Assume the Go code doesn't fail, so no need to map the failure back to Tcl

return TCL_OK;
}

(感谢 https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf 为我提供了足够的信息来计算一些类型绑定(bind)。)

这就是您向 Tcl 注册为回调的函数。

Tcl_CreateObjCommand(interp, "ip_v4_address", ip_address_glue, (ClientData)AF_INET, NULL);

理论上,命令注册可能会失败。实际上,只有在删除 Tcl 解释器(或其中的一些关键 namespace )时才会发生这种情况。


如果在 Go 级别将故障编码为枚举,则将故障映射到 Tcl 将是最简单的。可能最容易将成功表示为零。有了它,您就可以:

GoInt failure_code = ip_address(address_family, address);

switch (failure_code) {
case 0: // Success
return TCL_OK;
case 1: // First type of failure
Tcl_SetResult(interp, "failure of type #1", TCL_STATIC);
return TCL_ERROR;
// ... etc for each expected case ...
default: // Should be unreachable, yes?
Tcl_SetObjResult(interp, Tcl_ObjPrintf("unexpected failure: %d", failure_code));
return TCL_ERROR;
}

用值元组传回更复杂的返回类型(尤其是成功指示器和“真实”结果值的组合)也应该是可能的,但我没有 Go 开发环境来探究它们是如何实现的'映射到 C 级。

关于go - 从 Tcl 脚本调用 golang 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56385020/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com