Skip to content

Latest commit

 

History

History

dotnet-cpp-ffi1

C++ Interface with .NET (F# Fsharp).

Goals

This example shows how to interface a C++ shared library from .NET (F# language) on Linux.

Objective - Find out how to:

  • [ ] Pass and get arrays from C++ shared library.
  • [ ] Pass and get C-structs form C++ and C shared library.
  • [ ] Deal with C++ objects.
  • [ ] Pass STL vectors to C++.

Files:

  • hpc.cpp - C++ source code to build the Linux shared library hpc.so.
  • wrapper.fsx - F# code that calls the shared library hpc.so.
  • Makefile - Makefile build recipe to compile all sources.

Note:

  • hpc - stands for high performance computing.

Shared Libraries

OSSuffixDynamic LinkerObject Code file Format
Linux.sold.soELF
Mac OSX.dylibdyldMacO
Windows.dll or .OCX (OLE Libraries)PE - Portable Executable

Linux Tooling

g++GCC C++ Compiler
nm
ldd
strings
strace

Terminology

  • ABI - Application Binary Interface
  • API - Application Programming Interface
  • FFI - Foreign Function Interface
  • CLR - Common Language Runtime (.NET Framework virtual machine)
  • CIL - Common Language Infrastructure
  • COM - Component Object Model
  • Pinvoke - Platform Invocation Service. - The .NET FFI - Foreign Function Interface
  • Managed Code - Code that runs in a virtual machine such as JVM or .NET (CLR).
  • Unmanaged Code - Native code, bnary code. Generally a shared library such as *.dll (Windows) or *.so (Linux) files.
  • Marshalling -
  • Endianess
    • Little Endian
    • Big Endian
    • Network Order
  • Strings Representation (Enconding)
    • ACII - 8 bits characters
    • UTF-8
    • UTF-16
    • ISO-8859-1
    • ANSI
  • New Line Character
    • \n - CR - Carriage Return (Unix, Linux)
    • \r - LF -
    • \n\r - CRLF - Windows

Notes about C# - Pinvoke

  • C# Interface with unmanaged code (native code or shared libraries)
    • Pinvoke -
    • C++/CLI - Managed C++, A C++ version that compiles to the .NET virtual machine. It allows mixing managed and unmaneged C# code.
    • COM (Component Object Model) Objects - Downside: Only available on windows.
  • To interface C++ it is necessary to write a C-interface to the C++ shared library.
  • Only C-types can be marshalled. In order to to marshall a non C-type it is necessary to write C-wrapper or C-interface with “extern” and void* pointer.
  • Thre is no way to use a C++ class directly from a C# code. In order to use the C++ class, it is necesary to write c-wrappers for all C++ class methods that will be used and a .NET Pinvoke statement.
  • System.Runtime.InteropServices namespace.
  • StructLayout - C-struct.
  • Dllimport
    • EntryPoint
    • CharSet
      • CharSet.Auto
      • CharSet.Ansi
      • CharSet.Unicode
    • CallingConvention
      • CallingConvention.ThisCall
      • CallingConvention.Cdecl
      • CallingConvention.Winapi
    • SetLastError
  • MarshalAs
    • UnmanagedType.LPArray
    • MarshalAs(UnmanagedType.LPStr)
    • MarshalAs(UnmanagedType.LPStruct)
C-type / Function ParameterC# typeF# typeDescription
char*string, StringBuilder, byte [] or IntPtrConst char terminated by null
const char*
doubledoublefloat64-bit IEEE Float point number
(double xs [], int n)double []float []C array passed with its size.
& intref intref intC-pointer to a varible of type int passed by reference.
C Data Type.NET EquivalentC# Equivalent
char, booleanSystem.SBytesbyte
wchar_t, shortSystem.Int16short
unsigned char, byteSystem.Int33int
unsigned shortSystem.Uint16ushort
unsigned long, unsigned intSystem.Uint32uint
BSTR, char*, LPSTR, wchar_t*, LPWSTRSystem.Stringstring

C++ Notes

Converting std::vector to void*

From: c++ - how to convert std::vector<vector> to void* - Stack Overflow

C structs in C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct A
{
  int i:
  double d;
  .
  .
  . // and so on
}

[DllImport(Constants.LibraryPath, EntryPoint = "callculate", CallingConvention = CallingConvention.Cdecl)]
public static extern void callculate(ref A, int i);

Pinvoke Marshalling

Finding Shared Libraries in Linux

Show all system’s shared libraries.

$ strings -n5 /etc/ld.so.cache 
ld.so-1.7.0
glibc-ld.so.cache1.1
libzvbi.so.0
/usr/lib/libzvbi.so.0
libzvbi.so
/usr/lib/libzvbi.so
libzvbi-chains.so.0
/usr/lib/libzvbi-chains.so.0
libzvbi-chains.so
/usr/lib/libzvbi-chains.so
... ... ... 

Filter the shared libraries:

# GNU Scientific Library 
$ strings -n5 /etc/ld.so.cache | grep -i libgsl
libgslcblas.so.0
/usr/lib/libgslcblas.so.0
libgslcblas.so
/usr/lib/libgslcblas.so
libgsl.so.19
/usr/lib/libgsl.so.19
libgsl.so
/usr/lib/libgsl.so


# C-lib Math Library
$ strings -n5 /etc/ld.so.cache | grep -i libm.so
libm.so.6
/usr/lib/libm.so.6
libm.so.6
/usr/lib32/libm.so.6
libm.so
/usr/lib32/libm.so

# Libc
$ strings -n5 /etc/ld.so.cache | grep -i libc.so
libc.so.6
/usr/lib/libc.so.6
libc.so.6
/usr/lib32/libc.so.6

References

General

Useful C# References

C-interface

Other FFIs

GCC Manual

Numerical Libraries