Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ogxd/ffidji
🐶 FFIDJI is a tool to automatically generate bindings between languages, like calling Rust code from C# for instance.
https://github.com/ogxd/ffidji
cplusplus csharp dotnet ffi ffi-bindings interop interoperability pinvoke rust rust-lang
Last synced: about 1 month ago
JSON representation
🐶 FFIDJI is a tool to automatically generate bindings between languages, like calling Rust code from C# for instance.
- Host: GitHub
- URL: https://github.com/ogxd/ffidji
- Owner: ogxd
- Created: 2021-09-07T20:23:45.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2022-07-19T21:43:57.000Z (over 2 years ago)
- Last Synced: 2024-09-25T16:09:06.387Z (5 months ago)
- Topics: cplusplus, csharp, dotnet, ffi, ffi-bindings, interop, interoperability, pinvoke, rust, rust-lang
- Language: Rust
- Homepage: https://ogxd.github.io/ffidji
- Size: 3.08 MB
- Stars: 8
- Watchers: 2
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: Readme.md
Awesome Lists containing this project
- awesome-rust-list - ogxd/ffidji
- awesome-rust-list - ogxd/ffidji
README
# FFIDJI
FFIDJI is a Foreign Function Interface code generator.
You can use it to automatically generate bindings for simple to complex types and delegates between different languages, like calling Rust or C native code from C# for instance.
_(It actually works the same way with several different languages, checkout [documentation](https://ogxd.github.io/ffidji/) to see what's supported)_
## Supported Languages
- C# to RUST
- C# to C/C++_Many more to come!_
## [Full Documentation](https://ogxd.github.io/ffidji/)
## Benchmark
'''
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Allocated |
|--------------------- |--------------:|-------------:|-------------:|----------:|---------:|-------:|-------:|----------:|
| Concat Managed | 13.90 ns | 0.361 ns | 0.822 ns | 1.00 | 0.00 | 0.0076 | - | 48 B |
| Concat FFIDJI | 303.69 ns | 6.162 ns | 10.296 ns | 21.87 | 1.44 | 0.0076 | - | 48 B |
| Concat Protobuf Grpc | 217,729.81 ns | 4,329.875 ns | 7,807.658 ns | 15,756.08 | 1,126.16 | 1.4648 | 0.4883 | 9,795 B |
'''## Example
### Interface
```xml
```
### Command
`ffidji -f csharp MyCsharpProject/MyGeneratedInterface.cs -t c MyCppProject/MyHeader.h -i MyInterface.xml`
### Generated output
#### C#
```csharp
// Autogenerated by FFIDJIusing System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;using int8 = System.SByte;
using uint8 = System.Byte;
using int16 = System.Int16;
using uint16 = System.UInt16;
using int32 = System.Int32;
using uint32 = System.UInt32;
using int64 = System.Int64;
using uint64 = System.UInt64;
using float16 = System.Half;
using float32 = System.Single;
using float64 = System.Double;namespace FFIDJI
{
public static class SampleInterface
{
public const string LIBRARY_NAME = "MyNativeLibrary.dll";private readonly struct Arr
{
public readonly IntPtr ptr;
public readonly int size;
public Arr(IntPtr ptr, int size)
{
this.ptr = ptr;
this.size = size;
}
}private unsafe static T[] CopyArray(IntPtr ptr, int size) where T : unmanaged
{
int length = size * Marshal.SizeOf();
T[] array = new T[size];
void* u_src = ptr.ToPointer();
fixed (T* u_dst = &array[0])
{
Unsafe.CopyBlock(u_dst, u_src, (uint)length);
}
return array;
}private static T[] Convert(Arr arr) where T : unmanaged
{
return CopyArray(arr.ptr, arr.size);
}private static T Convert(T obj) where T : unmanaged
{
return obj;
}private unsafe static Arr Convert(T[] array) where T : unmanaged
{
int length = array.Length * sizeof(T);
IntPtr ptr = Alloc(length);
void* u_dst = ptr.ToPointer();
fixed (T* u_src = &array[0])
{
Unsafe.CopyBlock(u_dst, u_src, (uint)length);
}
return new Arr(ptr, array.Length);
}[DllImport(LIBRARY_NAME, EntryPoint = "Free_FFI")]
private static extern void Free(IntPtr ptr);[DllImport(LIBRARY_NAME, EntryPoint = "Alloc_FFI")]
private static extern IntPtr Alloc(int length);[StructLayout(LayoutKind.Sequential)]
public struct PairToSum
{
public int32 a;
public int32 b;
}[StructLayout(LayoutKind.Sequential)]
public struct ArrayToSum
{
public int32[] intsToSum;
}private static unsafe void Free(ArrayToSum_FFI input)
{
Free(input.intsToSum.ptr);
}[StructLayout(LayoutKind.Sequential)]
private struct ArrayToSum_FFI
{
public Arr intsToSum;
}private static ArrayToSum Convert(ArrayToSum_FFI data_FFI)
{
return new ArrayToSum
{
intsToSum = Convert(data_FFI.intsToSum),
};
}private static ArrayToSum_FFI Convert(ArrayToSum data)
{
return new ArrayToSum_FFI
{
intsToSum = Convert(data.intsToSum),
};
}private unsafe static ArrayToSum[] Convert(Arr arr)
{
var array_ffi = CopyArray(arr.ptr, arr.size);
var array = new ArrayToSum[arr.size];
for (int i = 0; i < arr.size; ++i) array[i] = Convert(array_ffi[i]);
return array;
}[DllImport(LIBRARY_NAME, EntryPoint = "Sum")]
private extern static int32 Sum_FFI(int32 A, int32 B);public static int32 Sum(int32 A, int32 B)
{
var A_ffi = Convert(A);
var B_ffi = Convert(B);
var result_ffi = Sum_FFI(A_ffi, B_ffi);
var result = Convert(result_ffi);
return result;
}[DllImport(LIBRARY_NAME, EntryPoint = "SumPair")]
private extern static int32 SumPair_FFI(PairToSum input);public static int32 SumPair(PairToSum input)
{
var input_ffi = Convert(input);
var result_ffi = SumPair_FFI(input_ffi);
var result = Convert(result_ffi);
return result;
}[DllImport(LIBRARY_NAME, EntryPoint = "SumArray")]
private extern static int32 SumArray_FFI(ArrayToSum_FFI input);public static int32 SumArray(ArrayToSum input)
{
var input_ffi = Convert(input);
var result_ffi = SumArray_FFI(input_ffi);
Free(input_ffi);
var result = Convert(result_ffi);
return result;
}
}
}
```#### C/C++
You only need to implement generated interface!
```c++
// Autogenerated by FFIDJI#include
#include#ifdef __cplusplus
extern "C"
{
#endiftypedef int8_t int8;
typedef uint8_t uint8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int32_t int32;
typedef uint32_t uint32;
typedef long int64;
typedef unsigned long uint64;
typedef float float32;
typedef double float64;__declspec(dllexport) inline void* Alloc_FFI(int32 length)
{
return (void*)malloc(length);
}__declspec(dllexport) inline void Free_FFI(void* ptr)
{
free(ptr);
}struct PairToSum
{
int32 a;
int32 b;
};struct ArrayToSum
{
int32* intsToSum_ptr;
int intsToSum_len;
};__declspec(dllexport) int32 Sum(int32 A, int32 B);
__declspec(dllexport) int32 SumPair(PairToSum input);
__declspec(dllexport) int32 SumArray(ArrayToSum input);
#ifdef __cplusplus
}
#endif
```## Links
See [The Rust FFI Omnibus](http://jakegoulding.com/rust-ffi-omnibus/string_arguments/) for more info on how to marshal to rust