如何在C中删除”extern”函数并能够从Golang中使用它们?

huangapple go评论72阅读模式
英文:

How to remove "extern" functions in C and be able to use them from golang?

问题

我有一个C++库的C包装器,我想在golang中使用它。我想要的回调路径是golang->C->C++。我已经测试了C->C++部分,但在golang->C部分遇到了困难。

根据维基百科上的说法,我尝试了这个示例(https://github.com/golang/go/wiki/cgo#function-variables)。在Linux上运行良好,但在Windows上编译时失败,因为我将C库和golang分开编译。

我认为可以将C库分成完全不了解golang的部分,并将带有"extern"关键字的回调放入golang目录。但我认为这对我来说不合适,因为我需要的函数看起来像这样:

ClipperPaths64 *
clipper_clipperoffset_execute_gocallback(void *mem, ClipperClipperOffset *c, uintptr_t h) {
        auto result = new (mem) Paths64();
        from_c(c)->Execute(from_c(h), *result);
        return to_c(result);
}

你看到我使用了from_c(...)函数,它们返回C++对象,它们没有公开在这个库中,我不能使用它们。

如果有帮助的话,我可以分享更多的代码。

英文:

I have a C wrapper of C++ library that I want to use with golang. Overall path of callback that I want is golang->C->C++. I tested part C->C++, but face difficulties with golang->C part.

As said in wiki, I tried this example. It works good on linux, but when I compile it on windows it fails on "extern" keyword because I compile C library and golang separately.

I thought that it is possible to split C library on part that doesn't know about golang at all. And put this callback with "extern" keyword into golang directory. But I think this will not fit me because function that takes callback and I need looks like this:

ClipperPaths64 *
clipper_clipperoffset_execute_gocallback(void *mem, ClipperClipperOffset *c, uintptr_t h) {
        auto result = new (mem) Paths64();
        from_c(c)->Execute(from_c(h), *result);
        return to_c(result);
}

You see that I use from_c(...) functions and they return C++ objects, they are not exposed publicly of this library and I cannot use them.

I would share more code if it would be helpful.

答案1

得分: 0

好的,以下是翻译好的内容:

解决方案:
只需将“extern”函数移动到golang模块的目录中。您将单独编译C/C++库,并将回调函数和在golang文件中定义的任何内容放置在与golang代码相邻的位置。

callback.c示例:

// 定义delta回调函数
double delta_callback(
    uintptr_t h,
    ClipperPath64 *path, ClipperPathD *path_normals,
    size_t curr_idx, size_t prev_idx)
{
    return goDeltaCallback64(h, path, path_normals, curr_idx, prev_idx);
}

callback.h:

#ifndef CLIBRARY_H
#define CLIBRARY_H

#include <stddef.h>
#include "../lib/clipper2c/clipper2c.h"

typedef double (*callbackfunc) (
    uintptr_t h, ClipperPath64 *path, ClipperPathD *path_normals,
                    size_t curr_idx, size_t prev_idx);

double delta_callback(
    uintptr_t h,
    ClipperPath64 *path, ClipperPathD *path_normals,
    size_t curr_idx, size_t prev_idx);

extern double goDeltaCallback64(uintptr_t h, ClipperPath64 *path,
                                ClipperPathD *path_normals, size_t curr_idx,
                                size_t prev_idx);

#endif

.go文件:

//export goDeltaCallback64
func goDeltaCallback64(
	h C.uintptr_t,
	path *C.ClipperPath64,
	path_normals *C.ClipperPathD,
	curr_idx C.size_t,
	prev_idx C.size_t,
) C.double {
	fn := cgo.Handle(h).Value().(ClipperOffsetCallback)

	gopath := &Path64{
		p: path,
	}

	gopath_normals := &PathD{
		p: path_normals,
	}

	return C.double(fn(gopath, gopath_normals, int(curr_idx), int(prev_idx)))
}
英文:

Well, it is solved and as reference you may peek my repo: here

Solution:
Just move function that is "extern" to directory of golang module. You will compile separately C/C++ library and alongside golang code you can place callbacks and whatever you will define in golang file.

Example of callback.c:

// define delta callback
double delta_callback(
    uintptr_t h,
    ClipperPath64 *path, ClipperPathD *path_normals,
    size_t curr_idx, size_t prev_idx)
{
    return goDeltaCallback64(h, path, path_normals, curr_idx, prev_idx);
}

callback.h:

#ifndef CLIBRARY_H
#define CLIBRARY_H

#include &lt;stddef.h&gt;
#include &quot;../lib/clipper2c/clipper2c.h&quot;

typedef double (*callbackfunc) (
    uintptr_t h, ClipperPath64 *path, ClipperPathD *path_normals,
                    size_t curr_idx, size_t prev_idx);

double delta_callback(
    uintptr_t h,
    ClipperPath64 *path, ClipperPathD *path_normals,
    size_t curr_idx, size_t prev_idx);

extern double goDeltaCallback64(uintptr_t h, ClipperPath64 *path,
                                ClipperPathD *path_normals, size_t curr_idx,
                                size_t prev_idx);

#endif

.go:

//export goDeltaCallback64
func goDeltaCallback64(
	h C.uintptr_t,
	path *C.ClipperPath64,
	path_normals *C.ClipperPathD,
	curr_idx C.size_t,
	prev_idx C.size_t,
) C.double {
	fn := cgo.Handle(h).Value().(ClipperOffsetCallback)

	gopath := &amp;Path64{
		p: path,
	}

	gopath_normals := &amp;PathD{
		p: path_normals,
	}

	return C.double(fn(gopath, gopath_normals, int(curr_idx), int(prev_idx)))
}

huangapple
  • 本文由 发表于 2023年5月26日 15:31:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76338574.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定