Calling the Rust client libs from C

Hi there. I’m trying to get started developing an iOS app that will connect to the Maidsafe API. I know there is a Xamarin project going on, but I want to try calling the Rust libraries from C (or Objective-C) first.

Has anyone done this before? I couldn’t find any examples of it.

I checked out the safe_client_libs repo and tried using cbindgen to generate C header files for all the Rust functions. However cbindgen chokes on the FFI* classes and can’t generate headers for them, I’m not quite sure why. Then I learned about the auto-gen/c-include directory, which already contains all the header files I need. However, trying to import safe_app.h or safe_core.h results in a bunch of unknown type errors. I haven’t written C for a long time, so I may be missing something obvious. Does anyone have any pointers? My main.c file looks like this:

#include <stdint.h>
#include <stdio.h>
#include "c-include/safe_core.h"
#include "c-include/safe_app.h"

int main() {
    login("secret", "pass", 0, 0, 0);
    return 0;
}

(and I know calling login with 0s won’t work, I’m just trying to get something to compile right now)

1 Like

Is your “c-include” subdirectory in the same directory as your main.c file? Or does the compiler otherwise know how to find the “c-include” directory?

Yeah, it is. Copied right from the safe_client_libs repo.

I don’t see those header files in the repo that you linked, but I think maybe you need to link to a library? See: https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_C_libraries.html

Yes, the auto-gen/c-include directory doesn’t get generated until you build the project, and it isn’t committed in git. I have built the safe_client_lib .dylibs and I am linking them with -L, but the compiler isn’t even making it to the link phase so that isn’t the problem.

Hi,

Yes, the C headers should be already there. However, I have checked your sample code and you are right about the fact that it’s not possible to use them currently due to missing type definitions.

Here’s a tracking issue in JIRA: [MAID-2576] - JIRA
We’ll fix this soon - thank you for reporting!

4 Likes

Hey! It looks like the C headers are done! I pulled down the latest version of the safe_client_libs repo and I’m trying to build it in order regenerate the header files. But I am getting a build error:

  = note: Undefined symbols for architecture x86_64:
            "_test_simulate_network_disconnect", referenced from:
                _Java_net_maidsafe_safe_1app_NativeBindings_testSimulateNetworkDisconnect in safe_app_jni.2aqc199ljf8r6eqm.rcgu.o
            "_test_create_app_with_access", referenced from:
                _Java_net_maidsafe_safe_1app_NativeBindings_testCreateAppWithAccess in safe_app_jni.2aqc199ljf8r6eqm.rcgu.o
            "_test_create_app", referenced from:
                _Java_net_maidsafe_safe_1app_NativeBindings_testCreateApp in safe_app_jni.2aqc199ljf8r6eqm.rcgu.o
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)


error: aborting due to previous error

error: Could not compile `safe_app_jni`.

I am on rustc 1.26.2 and macOS 10.13.5. I am building using the following command: cargo build --features "use-mock-routing testing". I have tried building the head of master (3ba809f197e) as well as the last official release (cc4849874).

Am I missing anything or is there a problem with the library?

Hi @mplorentz! Looks like you’re building safe_client_libs from the project’s root folder. For the safe_app C-bindings you’ll need to run cargo build --features "use-mock-routing bindings" from the safe-app folder in safe_client_libs. This would generate the bindings to safe_client_libs/bindings/c/safe-app.

Hope this clears things up. :slight_smile:

3 Likes

Thanks @lionel.faber . I can compile successfully in the safe_app folder, but it seems like the bindings that are generated in bindings/c/safe_app are incomplete, as I get a bunch of ‘unknown type’ errors if I try to import bindings/c/safe_app/safe_app.h into a C file. The same happens if I try to import bindings.h at the top level as well. Do you know what else I need to do to import the bindings?

Hey @mplorentz! I tried out importing the c-bindings for the first time myself today. These are the steps I followed:

  • Copy the entire bindings/c/safe_app folder into my project folder.
  • Create a C file that just prints Hello World, but, imports safe_app/safe_app.h too.

This is what it my project folder looks like:

.
├── a.out
├── safe_app
│   ├── ffi_utils.h
│   ├── safe_app
│   │   ├── access_container.h
│   │   ├── cipher_opt.h
│   │   ├── crypto.h
│   │   ├── immutable_data.h
│   │   ├── ipc.h
│   │   ├── logging.h
│   │   ├── mdata_info.h
│   │   ├── mutable_data
│   │   │   ├── entries.h
│   │   │   ├── entry_actions.h
│   │   │   ├── metadata.h
│   │   │   └── permissions.h
│   │   ├── mutable_data.h
│   │   ├── nfs.h
│   │   ├── object_cache.h
│   │   ├── safe_app.h
│   │   └── test_utils.h
│   ├── safe_app.h
│   └── safe_core
│       ├── arrays.h
│       ├── ipc
│       │   ├── req.h
│       │   └── resp.h
│       ├── nfs.h
│       └── safe_core.h
└── sample.c

And my sample.c is just:

#include<stdio.h>
#include "safe_app/safe_app.h"
int main() {
        printf("Hello World\n");
        return 0;
}

The above compiled and executed successfully. Are you doing something similar ?

1 Like

Ah, looks like I was importing bindings/c/safe_app/safe_app/safe_app.h instead of bindings/c/safe_app/safe_app.h. Thanks for your help!

3 Likes