gpt4 book ai didi

Java 外部函数接口(interface) (FFI) 与 C++ 互操作?

转载 作者:行者123 更新时间:2023-12-05 03:22:48 24 4
gpt4 key购买 nike

从 Java 18 开始,孵化的外部函数接口(interface)似乎没有处理 C++ 代码的好方法。我正在从事一个需要绑定(bind)到 C++ 的项目,我想知道如何避免在 C 中创建 thunk 库。

其中一个 C++ 类看起来像这样:

namespace library {

typedef uint8_t byte;

class CppClass {
public:
static oncstexpr const char* DefaultArgument = "default";

CppClass(const std::string& argument = DefaultArgument);
virtual ~CppClass();

bool doStuff();

bool handleData(std::vector<byte>* data);

private:
std::unique_ptr<InternalType> internalState;
};

}

我想创建一个类似于以下内容的 Java 类来反射(reflect)(省略错误检查):

public final class CppClass implements AutoCloseable {
public static final String DefaultArgument = "default";

private static final MethodHandle NEW;
private static final MethodHandle FREE;
private static final MethodHandle DO_STUFF;
private static final MethodHandle HANDLE_DATA;

static{
var binder = Natives.getBinder();
NEW = binder.bind("(manged constructor)", ValueLayout.ADDRESS, ValueLayout.ADDRESS);
FREE = binder.bindVoid("(manged deconstructor)", ValueLayout.ADDRESS);
DO_STUFF = binder.bind("(manged doStuff)", ValueLayout.JAVA_BYTE, ValueLayout.ValueLayout.ADDRESS);
HANDLE_DATA = binder.bind("manged handleData)", ValueLayout.JAVA_BYTE, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG);
}

private final MemorySegment pointer;

public CppClass() {
this(DefaultArgument);
}

public CppClass(String argument) {
try(var scope = MemoryScope.newConfinedScope()) {
var allocator = MemoryAllocator.nativeAllocator(scope);
pointer = (MemoryAddress)NEW.invokeExact(
allocator.allocateUtf8String(argument)
);
}
}

@Override
public void close() {
FREE.invokeExact(pointer);
}

public boolean doStuff() {
return (byte)DO_STUFF.invokeExact(pointer) != 0;
}

public boolean handleData(MemorySegment segment) {
return (byte)HANDLE_DATA.invokeEact(pointer, segment.address(), segment.byteSize()) != 0;
}
}

Binder 看起来像这样:

public interface Binder {
MethodHandle bind(String name, FunctionDescriptor desc);
MethodHandle bind(String name, MemoryLayout result, MemoryLayout... args);
MethodHandle bindVoid(String name, MemoryLayout... args);
}

我不确定其中哪些部分是正确的。我最大的实现问题是:

  • 调用构造函数和析构函数的正确方法是什么?
  • 调用方法的正确方法是什么?
  • 处理标准类型(std::string、std::vector)的正确方法是什么
  • C++ 编译器是在编译时添加默认参数值,还是生成多个方法?

最佳答案

所以一般的答案似乎是“只创建一个 shim 库”,因为 C++ ABI 更加流畅并且不受 Java 支持。

至于最后的答案:

  • 你就像平常一样做,但使用 void* 指针
  • this 作为 void* 传入并将其视为不透明指针
  • 在 shim 中自动处理,根据我收集的 std::string 制作拷贝并具有内部引用计数
  • 默认参数在编译时处理

关于Java 外部函数接口(interface) (FFI) 与 C++ 互操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72623896/

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