Click here to Skip to main content
15,311,151 members
Articles / Programming Languages / C#
Posted 10 Jan 2014


15 bookmarked

C# .NET Interoperability with Native C Libraries on Cross Platform : PART I

Rate me:
Please Sign up or sign in to vote.
4.33/5 (5 votes)
10 Jan 2014CPOL3 min read
This tip is to showcase how to write “Native C Library” so that it can be used for Cross Platform with .NET interoperability with Native C Libraries.
Image 1


This tip is all about how to manage .NET framework interoperability at cross platform level when C#. NET application needs to be portable on Windows as well as Linux.


As software technologies are very much advanced, that has encouraged many software firms to leverage it for changing Look and Feel of their old piece of software, improving the user experience by using available managed codes like C#. However, the task of converting huge stable legacy native code into equivalent C# is a real challenge and nightmare in terms of time and complexity of converting domain business logic written in C to equivalent C# managed code. Hence, one of the best approaches is to reuse existing stable native libraries with the help of .NET interoperability concept.

Secondly, many software firms are willing to support multiple freely available Operating Systems to reduce licensing cost and increase customer base by providing portability of their software on those freely available operating systems which need little tweak in Native C libraries as well as managed C# code. So, the above topics are addressed at beginner level. More articles would be added on the same in future.

Using the Code

There are two parts of this tip. First one focuses on the C Native Libraries, how to make it supported by cross platforms. Here below, I have given an example for libctest C Library.

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#ifdef __cplusplus    // If used by C++ code, 
extern "C" {          // we need to export the C interface
        typedef struct Temp
        {       int * iVal;
               char * chVal;
        /*___________________PLATFORM BASED EXPORT DECLARATION STARTS_____*/
               #ifdef UNIX 
                       #define EXPORT extern
               #elif (defined (_WINDOWS))
                       #define EXPORT extern __declspec( dllexport )
        /*___________________PLATFORM BASED EXPORT DECLARATION ENDS________*/
        EXPORT void ctestFreeResource (void * ptr)
               if(ptr) free(ptr);
               ptr = NULL;
        EXPORT void ctestFillStructure(MyTemp *iTempVal)
               iTempVal->iVal = (int*) malloc(sizeof(int));
               iTempVal->chVal = (char*) malloc(5);  
               *((*iTempVal).iVal) = 500;
#ifdef __cplusplus

Define EXPORT preprocessor macro based on the platform and declare each API with EXPORT to export API. Two APIs are defined for demonstration namely ctestFillStructure to fill structure with values and second is ctestFreeResource to free the heap memory allocated during native C APIs.

Compiling and Linking the C Library on Linux Platform

From downloaded demo project, unzip NativeCLib folder located under linux at /tmp or some other location on Linux system which is accessible and run the ./ shell script file at command prompt that will execute below commands to compile and link the libctest library and will generate shared object (Dynamic shared library) on same path:

 COMPILE       :       gcc -c -Wall -Werror -fpic ./ctest.c -DUNIX
 LINK          :       gcc -shared -o ctest.o

Compiling and Linking the C Library on Windows Platform

From downloaded demo project, unzip NativeTestLib library located under win folder and open the NativeTestLib.sln solution in MS-Visual Studio on Windows system and build it.

Below is demo C# code to use above native C library APIs:

using System;
using System.Runtime.InteropServices;
using System.Collections;
namespace UseSharedObject
        public  struct Temp
               public IntPtr  m_iVal;
               public  string m_strVal;
        class MainClass
        #if (UX_PLATFORM)      
               [DllImport ("./assembly/", EntryPoint="ctestFillStructure")]
                private static extern void ctestFillStructure(ref Temp i);
               [DllImport ("./assembly/", EntryPoint="ctestFreeResource")]
               private static extern void ctestFreeResource(IntPtr ptr);    
        #elif (WINDOWS)
               [DllImport ("./assembly/libctest.dll", EntryPoint="ctestFillStructure")]
                private static extern void ctestFillStructure(ref Temp i);
               [DllImport ("./assembly/libctest.dll", EntryPoint="ctestFreeResource")]
               private static extern void ctestFreeResource(IntPtr ptr);     
               public static  void Main (string[] args)
                       Temp valTemp = new Temp();                    
                       ctestFillStructure(ref valTemp);                      
                       Console.WriteLine ("RETURN VALUES FROM NATIVE LIBRARIES: 
                       valTemp.m_iVal = {0} valTemp.m_strVal = {1} ", 
                       Marshal.ReadInt32( valTemp.m_iVal), valTemp.m_strVal);
                       Console.WriteLine ("CURRENT  PLATFORM = {0}", 
                       ctestFreeResource( (IntPtr) (valTemp.m_iVal));                       
                       valTemp.m_iVal = (IntPtr)0;                   

Declare DllImport by passing library name and EntryPoint with C native function name which will be called in C# managed code followed by signature of native call with private static extern. Also define equivalent Temp structure in C# similar to Temp structure in C Library so can be passed as a parameter. Add UX_PLATFORM switch while creating C# project on Linux platform using monoDevelop or any other available IDE based on mono framework.

Copy the above generated on Linux or libctest.dll on Windows at assembly folder on same path of UseSharedObject C#.NET executable.

For quick demonstration, unzip Managed_C#_Code folder from downloaded demo project and open UseSharedObject.sln project in Microsoft Visual Studio on Windows operating system and MonoDevelop IDE or any other equivalent IDE on mono platform at Linux OS and build the solution. And run it.

Points of Interest

As ref in C# doesn’t support for pointer data type function parameters i.e. IntPtr, so in function ctestFreeResource, after de-allocation of pointer type variable, we assign it NULL in native library function call, however it does not reflect at C# code after returning from function so explicitly it has to be assigned with NULL value i.e. 0.

valTemp.m_iVal = (IntPtr)0; 


  • This is a first draft version.
  • Please visit this link to read Part II.   


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

India India
I am homemaker, a computer savvy and like to learn new technologies in IT world.

Comments and Discussions

GeneralNot so portable Pin
Carlos190712-Jan-14 22:43
professionalCarlos190712-Jan-14 22:43 
GeneralRe: Not so portable Pin
FIorian Schneidereit17-Jan-14 10:59
MemberFIorian Schneidereit17-Jan-14 10:59 
GeneralRe: Not so portable Pin
deepi201418-Jan-14 3:02
Memberdeepi201418-Jan-14 3:02 
GeneralMy vote of 4 Pin
Mohit Gonduley11-Jan-14 18:55
MemberMohit Gonduley11-Jan-14 18:55 
QuestionA little tip PinPopular
FIorian Schneidereit11-Jan-14 7:07
MemberFIorian Schneidereit11-Jan-14 7:07 
AnswerRe: A little tip Pin
deepi201417-Jan-14 9:05
Memberdeepi201417-Jan-14 9:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.