Rust: Refer to a third .rs file from a second .rs file [duplicate] - file

This question already has answers here:
How to access modules from parent or sibling folder modules?
(2 answers)
Closed last month.
I have three files:
// a.rs
struct MyThing {
}
// b.rs
mod a;
struct That {
mything: &a::MyThing;
}
// main.rs
mod a;
mod b;
fn main() {
let thing= a::MyThing{};
let that= b::That{myThing: &thing};
}
The compile error I get for a.rs is:
file not found for module b
help: to create the module b, create file "src/a/b.rs" or "src/a/b/mod.rs"
I thought I would need mod a; so that I can access the module in a.rs, but it looks like since mod b; is in main.rs, the mod a; inside b.rs is interpreted relative to b...or something.
How do I use one .rs file from another?

mod a; does not just declare or make reference to the module, a, it defines the module, a. Putting mod a; in b.rs creates a separate module from that created in main.rs. Instead, let main.rs create the modules and make reference to a in b. In this case, you need to make reference it according to its crate. In which crate is the module ./b.rs? The root crate, crate:
// b.rs
use crate::a;
struct That {
mything: &a::MyThing;
}

Related

Implementing Rust generated API in C using Webassembly

I have the following problem/task and I don't know how to approach it.
So I have a complex project where Developers can add plugins without changing anything on the system. For this there is a simple API. To develop a plugin, the developer has to implement a trait - this is how it would look like in Rust:
// Own struct
struct TestHandler;
impl FileHandler for TestHandler {
fn new() -> Self {
TestHandler
}
fn parse_files(&self, files: Files) -> Result<ParseFileResponse, Error> {
Ok(ParseFileResponse {
files,
metadata: MetaData { data: Vec::new() },
})
}
fn load_files(&self, files: Files, _meta: MetaData) -> Result<Files, Error> {
Ok(files)
}
}
export_file_handler_api!(TestHandler);
As I mentioned, the backend supports webassembly. So the task is to not use Rust for the generating a plugin but C. Goal to get a .wasm-binary at the end which implements the filehandler-API and exports the following functions: (C-Signature)
// Returns a ptr to a file handler
// The pointer is passed to the other functions
unsigned int new_handler();
// Destructs a file handler construted with new_handler
void destroy_handler(unsigned int);
// Returns a ptr to a result of Files/Error
// Arguments:
// 1. file handler ptr
// 2. ptr to files struct
// 3. ptr to MetaData struct
unsigned int load_files(unsigned int, unsigned int, unsigned int);
// Returns a ptr to a result ParsedFileRespons/Error
// Arguments:
// 1. file handler ptr
// 2. ptr to files struct
unsigned int parse_files(unsigned int, unsigned int);
My question would be: How to I approach this task implementing these functions - what do I have to import and how to I handle the pointers to my own struct?

How to make a plugin interface for a C program

I'm looking for a way to create a plugin interface for a C program. In the interest of a short and concise example, let's say I have the following program:
#include <stdio.h>
int complexFunction(int a, int b) { return a+b; }
int main() {
int a = 3;
int b = 6;
printf("The result of C(a, b) is %d.\n", complexFunction(a, b));
return 0;
}
Instead of using the defined complexFunction however, I would like to allow the user to code their own and then plug-in their implementation.
I have never worked with plugin implementations myself, but so far I have been able to come up with the following possibilities for a plugin interface:
Create a 'mini scripting language' which my program can parse and create a procedure pipeline for, then pass the variables into that pipeline. This would involve a lot of 'generic' functions for each possible action in the scripting language.
Use a pre-existing scripting language for the same purpose (however this may not be possible as I would need some very specialised scriptable functions).
Allow the user to write and compile a C file containing the definition of complexFunction(int, int), and dynamically load that at run-time. This is the least secure option but for development purposes it would be ideal as (only) I would author my own plugins and I could dynamically add functionality to my program.
My question is twofold:
What are the common ways of handling plug-in capabilities in Applications?
How can I accomplish (3) / is (3) even possible in C? After fopen-ing a file, can I somehow use it as code in the current program?
A scripting language (usually a pre-existing one like lua or something) is the most common way. 3 is possible- you could look in a predefined folder for dynamic libraries (.so or .dll files) and look for functions with specific names. Its doable, but there's huge security issues with it (you have no security really).
3)
If the user can compile your function into a .dll, you can use the following steps:
a) use LoadLibrary to load the dll
b) use GetProcAddress to get the address of the function
c) execute the function
Example:
typedef int (__cdecl *PCF)(int, int);
HMODULE hDll = LoadLibrary("x:\\Dllpath\\MyPlugIn.dll");
if (hDll != NULL)
{ PCF pfnComplexFunction = GetProcAddress(hDll, "complexFunction");
if (pfnComplexFunction != NULL)
{ int a = 3;
int b = 6;
printf("The result of C(a, b) is %d.\n", pfnComplexFunction(a, b));
}
FreeLibrary(hDll);
}
The function in the dll would need to be declared like
__declspec(dllexport) int __cdecl complexFunction(int a, int b)
{ return a + b;
}

C append to an array in header file

I have multiple header files, each of them must append a number to an array to register it's functions.
Currently I have a function with a unique name in each header file, and in the program file I need to call all those functions in one combining function.
int register1() { return 100; }; //in header1.h
int register2() { return 200; }; //in header2.h
int register3() { return 300; }; //in header3.h
int register4() { return 400; }; //in header4.h
int registered[] = {register1(),register2(),register3(),register4()}; //main.c
But this is quite inconvenient because I need to modify in two places when I add or remove header files. Better would be to modify the header file only. I was thinking about a preprocessor define, so in each header I can just use something like:
#define Registered Registered,100 // header1.h
#define Registered Registered,200 // header2.h
int registered[] = {Registered}; // main.c
But this of course will not compile, because new define redefines the old one. So is there a way to append a define? Or other way to append a number to an array without modifying two files?
This is C, not C++, otherwise I would use a class instance with constructor that would just write to an array. Somethink like that:
struct __header1{ __header1() {
global_array[global_array_ptr++] = 100;
} } __header1_inst;
and then convert it to a nice macro:
#define register(hdr, func) struct __header##hdr{ __header##hdr() { \
global_array[global_array_ptr++] = func; \
} } __header##hdr##_inst;
register(1, 100) // header1.h
register(2, 200) // header2.h
IMHO, this is a hack and I would advise against it. Even if you could do that in C, consider situation where one such header file is included by several modules. There will be an identical entry in the global array for every such module. Next, even though you can do it in C++, the order of global object initialization is undefined there, so initialization of another global object relying on contents of the global array will be unreliable.
Additionally, this is a really complicated way to do a simple thing, and obscures the meaning considerably. Apart from the array-filling code itself being complex, tracking includes will become burdensome when dependencies get beyond trivial. So, just fill that global array in a specific place explicitly.

Preferred Approach to Organizing ANSI C Project?

I'm a new C programmer, so this is a pretty basic question. What is the preferred approach to organizing ANSI C files in a project? I have about a dozen .c files each with their own .h file to hold local declarations, enums, etc. But I also have quite a few global parameters such as...
float LandingAltitudeList[2][17] = {
// P100
{12,-1000,0,1000,2000,3000,4000,5000,6000,7000,8000,9000,10000},
// P300
{16,-1000,0,1000,2000,3000,4000,5000,6000,7000,8000,9000,10000,1000,12000,13000,14000} };
enum PType {P100,P300};
enum Boolean {No=0,Yes=1,Off=0,On=1};
In addition, I have a number of global variables such as...
float Alt_min = LandingAltitudeList[PhenomType][1];
int Max = LandingAltitudeList[PhenomType][0];
float Alt_max = LandingAltitudeList[PhenomType][Max];
which I calculate just once, but use throughout the project. These need to be in a function in order to work.
How should I organize my files to handle these global parameters? Many thanks.
One option is to declare these variables in a header file. It would be probably more appropriate to make the variables themselves invisible and to declare access functions to interface them. Consider the following example:
/* in access.h */
int access_secret();
...
/* in access.c */
/* the private variable */
static int very_secret;
void calculate_secret() {
very_secret = 42;
}
void access_secret() {
return very_secret;
}
calculate_secret is called just once, when the module is initialized, and access_secret, when the variable value is needed. It is easy to enhance the system by adding array index parameter for arrays.

Call Go functions from C

I am trying to create a static object written in Go to interface with a C program (say, a kernel module or something).
I have found documentation on calling C functions from Go, but I haven't found much on how to go the other way. What I've found is that it's possible, but complicated.
Here is what I found:
Blog post about callbacks between C and Go
Cgo documentation
Golang mailing list post
Does anyone have experience with this? In short, I'm trying to create a PAM module written entirely in Go.
You can call the Go code from C. It is a confusing proposition, though.
The process is outlined in the blog post you linked to. But I can see how that isn't very helpful. Here is a short snippet without any unnecessary bits. It should make things a little clearer.
package foo
// extern int goCallbackHandler(int, int);
//
// static int doAdd(int a, int b) {
// return goCallbackHandler(a, b);
// }
import "C"
//export goCallbackHandler
func goCallbackHandler(a, b C.int) C.int {
return a + b
}
// This is the public function, callable from outside this package.
// It forwards the parameters to C.doAdd(), which in turn forwards
// them back to goCallbackHandler(). This one performs the addition
// and yields the result.
func MyAdd(a, b int) int {
return int( C.doAdd( C.int(a), C.int(b)) )
}
The order in which everything is called is as follows:
foo.MyAdd(a, b) ->
C.doAdd(a, b) ->
C.goCallbackHandler(a, b) ->
foo.goCallbackHandler(a, b)
The key to remember here is that a callback function must be marked with the //export comment on the Go side and as extern on the C side. This means that any callback you wish to use, must be defined inside your package.
In order to allow a user of your package to supply a custom callback function, we use the exact same approach as above, but we supply the user's custom handler (which is just a regular Go function) as a parameter that is passed onto the C side as void*. It is then received by the callbackhandler in our package and called.
Let's use a more advanced example I am currently working with. In this case, we have a C function that performs a pretty heavy task: It reads a list of files from a USB device. This can take a while, so we want our app to be notified of its progress. We can do this by passing in a function pointer that we defined in our program. It simply displays some progress info to the user whenever it gets called. Since it has a well known signature, we can assign it its own type:
type ProgressHandler func(current, total uint64, userdata interface{}) int
This handler takes some progress info (current number of files received and total number of files) along with an interface{} value which can hold anything the user needs it to hold.
Now we need to write the C and Go plumbing to allow us to use this handler. Luckily the C function I wish to call from the library allows us to pass in a userdata struct of type void*. This means it can hold whatever we want it to hold, no questions asked and we will get it back into the Go world as-is. To make all this work, we do not call the library function from Go directly, but we create a C wrapper for it which we will name goGetFiles(). It is this wrapper that actually supplies our Go callback to the C library, along with a userdata object.
package foo
// #include <somelib.h>
// extern int goProgressCB(uint64_t current, uint64_t total, void* userdata);
//
// static int goGetFiles(some_t* handle, void* userdata) {
// return somelib_get_files(handle, goProgressCB, userdata);
// }
import "C"
import "unsafe"
Note that the goGetFiles() function does not take any function pointers for callbacks as parameters. Instead, the callback that our user has supplied is packed in a custom struct that holds both that handler and the user's own userdata value. We pass this into goGetFiles() as the userdata parameter.
// This defines the signature of our user's progress handler,
type ProgressHandler func(current, total uint64, userdata interface{}) int
// This is an internal type which will pack the users callback function and userdata.
// It is an instance of this type that we will actually be sending to the C code.
type progressRequest struct {
f ProgressHandler // The user's function pointer
d interface{} // The user's userdata.
}
//export goProgressCB
func goProgressCB(current, total C.uint64_t, userdata unsafe.Pointer) C.int {
// This is the function called from the C world by our expensive
// C.somelib_get_files() function. The userdata value contains an instance
// of *progressRequest, We unpack it and use it's values to call the
// actual function that our user supplied.
req := (*progressRequest)(userdata)
// Call req.f with our parameters and the user's own userdata value.
return C.int( req.f( uint64(current), uint64(total), req.d ) )
}
// This is our public function, which is called by the user and
// takes a handle to something our C lib needs, a function pointer
// and optionally some user defined data structure. Whatever it may be.
func GetFiles(h *Handle, pf ProgressFunc, userdata interface{}) int {
// Instead of calling the external C library directly, we call our C wrapper.
// We pass it the handle and an instance of progressRequest.
req := unsafe.Pointer(&progressequest{ pf, userdata })
return int(C.goGetFiles( (*C.some_t)(h), req ))
}
That's it for our C bindings. The user's code is now very straight forward:
package main
import (
"foo"
"fmt"
)
func main() {
handle := SomeInitStuff()
// We call GetFiles. Pass it our progress handler and some
// arbitrary userdata (could just as well be nil).
ret := foo.GetFiles( handle, myProgress, "Callbacks rock!" )
....
}
// This is our progress handler. Do something useful like display.
// progress percentage.
func myProgress(current, total uint64, userdata interface{}) int {
fc := float64(current)
ft := float64(total) * 0.01
// print how far along we are.
// eg: 500 / 1000 (50.00%)
// For good measure, prefix it with our userdata value, which
// we supplied as "Callbacks rock!".
fmt.Printf("%s: %d / %d (%3.2f%%)\n", userdata.(string), current, total, fc / ft)
return 0
}
This all looks a lot more complicated than it is. The call order has not changed as opposed to our previous example, but we get two extra calls at the end of the chain:
The order is as follows:
foo.GetFiles(....) ->
C.goGetFiles(...) ->
C.somelib_get_files(..) ->
C.goProgressCB(...) ->
foo.goProgressCB(...) ->
main.myProgress(...)
It is not a confusing proposition if you use gccgo. This works here:
foo.go
package main
func Add(a, b int) int {
return a + b
}
bar.c
#include <stdio.h>
extern int go_add(int, int) __asm__ ("example.main.Add");
int main() {
int x = go_add(2, 3);
printf("Result: %d\n", x);
}
Makefile
all: main
main: foo.o bar.c
gcc foo.o bar.c -o main
foo.o: foo.go
gccgo -c foo.go -o foo.o -fgo-prefix=example
clean:
rm -f main *.o
The answer has changed with the release of Go 1.5
This SO question that I asked some time ago addresses the issue again in light of the 1.5 added capabilities
Using Go code in an existing C project
As far as I am concerned it isn't possible:
Note: you can't define any C functions in preamble if you're using
exports.
source: https://github.com/golang/go/wiki/cgo

Resources