Java FFM - неожиданное поведение с «указателями» [дублировать]C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Java FFM - неожиданное поведение с «указателями» [дублировать]

Сообщение Anonymous »

Чтобы попробовать API Java 25 FFM, я хотел вызвать код C ++ через C-обертку.

Код: Выделить всё

#pragma once

#include 

class Printer
{
public:
void print(const std::string& message);
};
< /code>
printer.cpp
#include "Printer.h"

void Printer::print(const std::string& message)
{
std::cout 
printerwrapper.cpp
#include "Printer.h"
#include "PrinterWrapper.h"

extern "C" {

Printer* newPrinter()
{
return new Printer();
}

void Printer_print(Printer* printer, const char message[])
{
printer->print(message);
}

void deletePrinter(Printer* printer)
{
delete printer;
}

}
< /code>
printer.java
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;

public class Printer {

private static final MethodHandle NEW_PRINTER;
private static final MethodHandle PRINTER_PRINT;
private static final MethodHandle DELETE_PRINTER;

private MemorySegment printerPointer;

static {
System.load("Path/to/shared/library");

Linker linker = Linker.nativeLinker();
SymbolLookup lookup = SymbolLookup.loaderLookup();

NEW_PRINTER = linker.downcallHandle(lookup.findOrThrow("newPrinter"),
FunctionDescriptor.of(ValueLayout.ADDRESS));
PRINTER_PRINT = linker.downcallHandle(lookup.findOrThrow("Printer_print"),
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS));
DELETE_PRINTER = linker.downcallHandle(lookup.findOrThrow("deletePrinter"),
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS));
}

public Printer() {
try {
printerPointer = (MemorySegment) NEW_PRINTER.invoke();
} catch (Throwable e) {
e.printStackTrace();
}
}

public void print(String message) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment nativeString = arena.allocateFrom(message);
PRINTER_PRINT.invokeExact(printerPointer, nativeString);
} catch (Throwable e) {
e.printStackTrace();
}
}

public void delete() {
try {
DELETE_PRINTER.invokeExact(printerPointer);
} catch (Throwable e) {
e.printStackTrace();
}
}

}
< /code>
main.java
public class Main {
public static void main(String[] args) {
Printer printer = new Printer();
printer.print("Hello World!");
printer.delete();
}
}
< /code>
Если я запускаю программу, все работает нормально. Но вот неожиданное поведение: если я изменяю переменную PrinterPointer 
на MemorySegment.null или любой сегмент памяти нулевой длины (см. Сегменты памяти нулевой длины в документации Java) любого адреса, например,. MemoreSegment.ofAddress (73928298) , программа все еще выполняется правильно.

Код: Выделить всё

    public Printer() {
printerPointer = MemorySegment.NULL;
}
< /code>
Второе изменение: < /p>
    public Printer() {
printerPointer = MemorySegment.ofAddress(73928298);
}
оба раза, Hello World! печатается на консоли. Но я не знаю, почему это работает оба раза, так как я ожидал, что это не так. Что -то не так с оберткой? (Как я узнал, вызов кода C ++ создает неопределенное поведение). Или это задумано по какой -то причине? Или это просто ошибка в API?


Подробнее здесь: https://stackoverflow.com/questions/797 ... h-pointers
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»