Параметры для использования в определении Vapi для передачи массивов по ссылке

У меня есть следующий код C, который использует libmodbus для чтения одного регистра устройства с использованием ModbusTCP:

modbus_t *ctx;
uint16_t tab_reg[16];

ctx = modbus_new_tcp("10.0.1.77", 502);
modbus_read_registers(ctx, 0x20, 2, tab_reg);

printf("reg = %d (0x%X)\n", tab_reg[0], tab_reg[0]);
printf("reg = %d (0x%X)\n", tab_reg[1], tab_reg[1]);

теперь пытаюсь переключить это на Vala с помощью сгенерированного мной Vapi, содержимое этого для нового и прочитанного:

[CCode (cheader_filename = "modbus.h", cname = "modbus_new_tcp")]
public static unowned Modbus.modbus_t create_tcp (string ip_address, int port);

public static int read_registers (Modbus.modbus_t ctx, int addr, int nb, uint16 dest);
[CCode (cheader_filename = "modbus.h")]

и переведенная программа Vala:

class ModbusReadTest : GLib.Object {

    unowned Modbus.modbus_t ctx;

    public void run () {
        uint16 reg = 0x00;

        ctx = create_tcp ("10.0.1.77", 502);
        Modbus.read_registers (ctx, 0x20, 2, reg);

        message ("reg = %d (0x%X)", reg, reg);

        Modbus.close(ctx);
    }
}

По совпадению, когда я компилирую это в код C, а затем в двоичный файл с помощью gcc, я получаю сообщение об ошибке:

read-registers-test.c:71:2: warning: passing argument 4 of ‘modbus_read_registers’ makes pointer from integer without a cast [enabled by default]

что не удивительно. Но я не уверен, как мне изменить содержимое Vapi, чтобы оно больше соответствовало прототипу в заголовке libmodbus:

int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);

Я пробовал сочетание параметров массива и использование «out», но не смог получить более одного двухбайтового регистра за раз.

Спасибо за любые предложения.


person Geoff Johnson    schedule 27.05.2013    source источник


Ответы (1)


read_registers, вероятно, должен быть методом экземпляра (в Modbus.modbus_t) вместо статического метода, а Modbus.modbus_t, вероятно, следует переименовать во что-то вроде Modbus.Context, create_tcp, вероятно, должен быть конструктором, а Modbus.close должен быть свободной функцией. в компактном классе Modbus.Context, но это не относится к этому вопросу (если вы зайдете на #vala на irc.gnome.org, вы можете получить помощь по этому вопросу).

Вероятно, вы хотите сделать его массивом:

public static int read_registers (Modbus.modbus_t ctx, int addr, [CCode (array_length_pos = 2.5)] uint16[] dest);

Затем вы должны сделать что-то вроде этого в Vala:

public void run () {
    uint16 reg[2];

    ctx = create_tcp ("10.0.1.77", 502);
    Modbus.read_registers (ctx, 0x20, reg);

    message ("reg = %d (0x%X)", reg, reg);

    Modbus.close(ctx);
}

Для порта, более точного к исходному C (где tab_reg имеет 16 элементов вместо 2), вы можете использовать нарезку массива:

public void run () {
    uint16 reg[16];

    ctx = create_tcp ("10.0.1.77", 502);
    Modbus.read_registers (ctx, 0x20, reg[0:2]);

    stdout.printf ("reg = %d (0x%X)\n", reg, reg);

    Modbus.close(ctx);
}

Обратите внимание, что если вы сделаете его методом экземпляра, вам нужно будет изменить array_length_pos на 1,5.

person nemequ    schedule 27.05.2013