How to access an array of function pointers with zero completion declared in C from Rust?

I have the following C code with a zero outline function pointers:

#include <stdio.h>

void hello_register(void) {
  printf("hello_register called\n");
}

void (*vlog_startup_routines[])() = {
    hello_register,
    0
};

This code has been compiled and linked to my Rust program using the Cargo script assembly. How can I call each of the function pointers in an array from Rust?

+2
source share
3 answers

The combination of the two previous answers looks better:

extern crate libc;

type VlogStartupRoutine = Option<extern "C" fn()>;

extern "C" {
    // This array is NULL-terminated; set the length to zero to
    // prevent any uncontrolled access.
    static vlog_startup_routines: [VlogStartupRoutine; 0];
}

fn main() {
    unsafe {
        let routines = vlog_startup_routines.as_ptr();

        for i in 0.. {
            match *routines.offset(i) {
                Some(routine) => {
                    println!("Calling startup routine #{}", i);
                    routine();
                }
                None => break,
            }
        }
    }
}

A symbol is vlog_startup_routinesnot a pointer to a pointer to a function, it is an array of pointers to functions. When you use a name vlog_startup_routinesin C code, the lvalue value of the array is forcibly bound to a pointer. This does not mean that the variable stores a pointer!

Rust, vlog_startup_routines . , , , NULL. , , .

Option<extern "C" fn()> , FFI .

+4

, vlog_startup_routines . ; . . C, :

int i = 7;
int a[1] = { 8 };
int *p = &i;

i , 7, a , (8), p , . , .

:

// Or whatever argument types
type VlogStartupRoutine = extern "C" fn();

extern "C" {
    static vlog_startup_routines: VlogStartupRoutine;
}

, vlog_startup_routines - , , C void *vlog_startup_routines.

unsafe {
    println!("{:p}", vlog_startup_routines);
    println!("{:p}", hello_register as *const ());
}

, vlog_startup_routines, .

() :

type VlogStartupRoutine = Option<extern "C" fn()>;

#[link(name = "funcref")]
extern "C" {
    static vlog_startup_routines: [VlogStartupRoutine;10];
    fn hello_register();
}

fn main() {
    unsafe {
        println!("{:p}", vlog_startup_routines.as_ptr());
        println!("{:p}", hello_register as *const ());
    }
    unsafe {
        let routine = vlog_startup_routines[0].unwrap();
        println!("Calling startup");
        routine();
        assert!(vlog_startup_routines[1].is_none());
    }
}

, Option<extern "C" fn()> .

:

0x7efc27d37030
0x7efc27b366f0
Calling startup
hello_register called

, "", , , .: -)

+3

:

extern crate libc;

// Or whatever argument types
type VlogStartupRoutine = extern "C" fn();

extern "C" {
    static vlog_startup_routines: VlogStartupRoutine;
}

fn main() {
    unsafe {
        let routine = vlog_startup_routines;
        println!("Calling startup");
        routine();
    }
}

, C : :

extern "C" {
    static vlog_startup_routines: VlogStartupRoutine;
    fn hello_register();
}

fn main() {
    unsafe {
        println!("{:p}", vlog_startup_routines);
        println!("{:p}", hello_register as *const ());
    }
}
0x1029bf750
0x1029bf750

, , , . vlog_startup_routines .

extern crate libc;

// Or whatever appropriate argument types
type VlogStartupRoutine = extern "C" fn();

extern "C" {
    #[link_name = "vlog_startup_routines"]
    static INITIAL_VLOG_STARTUP_ROUTINE: VlogStartupRoutine;
}

fn main() {
    unsafe {
        let startup_routines: *const VlogStartupRoutine = &INITIAL_VLOG_STARTUP_ROUTINE;

        for i in 0.. {
            let routine = *startup_routines.offset(i);

            let routine_as_ptr = routine as *const ();
            if routine_as_ptr.is_null() { break }

            println!("Calling startup routine #{}", i);
            routine();
        }
    }
}

, , , .

+1

Source: https://habr.com/ru/post/1660594/


All Articles