2

I have these C files and I want to use pair_add, add and PAIR from Rust.

adder.c

#include <stdlib.h>
#include "adder.h"

int pair_add(PAIR * ppair) {
    return ppair->x + ppair->y;
}

int add(int x, int y) {
    return x + y;
}

adder.h

typedef struct {
    int x;
    int y;
} PAIR;

int pair_add(PAIR * ppair);
int add(int, int);

I compile them using:

gcc -c adder.c
ar rc libadder.a adder.o  # Static link

The documentation does not detail how to integrate C typedef structs and the example is for functions which return and accept i32. Other online resources were also limited.

I attempted the following but could not add the PAIR typedef:

extern crate libc;

use libc::c_int;

#[link(name = "adder")]
extern "C" {
    // Define PAIR

    // int pair_add(PAIR * ppair);
    fn pair_add(input: Pair) -> c_int;

    // int add(int, int);
    fn add(input1: c_int) -> c_int;
}

fn main() {}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Greg
  • 8,175
  • 16
  • 72
  • 125
  • @Stargateur Updated the post and posted a new question on that topic https://stackoverflow.com/questions/50619070 – Greg May 31 '18 at 07:38

1 Answers1

5

First:

typedef struct {
    int x;
    int y;
} PAIR;

This declares an anonymous struct and this is not currently supported by Rust. There is a RFC that proposes to add anonymous types.

Secondly, a typedef is just an alias and the name of the struct isn't important to be compatible. That means that you can simply do:

extern crate libc;
use libc::c_int;

#[repr(C)]
struct PAIR {
    x: c_int,
    y: c_int,
}

// optional "equivalent" of typedef
type Pair = PAIR;

extern "C" {
    fn pair_add(input: *mut Pair) -> c_int;
    // could be
    // fn pair_add(input: *mut PAIR) -> c_int;
}

You could easily ignore the typedef and just use PAIR as a name for this struct. You can even just write struct PAIR; to make it opaque.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • You don't need to match the struct's name to start with, you can just do `#[repr(C)] struct Pair { x: c_int, y: c_int }`. You can give it any name you want, because as you mention, the name doesn't matter to the compiler. – Shepmaster May 31 '18 at 13:51
  • 2
    *to make it opaque* — I would **not** use this to define an opaque type. [Another Q&A has suggestions](https://stackoverflow.com/q/38315383/155423), but `struct PAIR;` would allow *anyone* to create an instance of a `PAIR`, which should not be allowed if it's opaque. – Shepmaster May 31 '18 at 13:53