Click here to Skip to main content
13,088,507 members (53,497 online)
Click here to Skip to main content
Add your own
alternative version


10 bookmarked
Posted 17 Jan 2014

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

, 17 Jan 2014
Rate this:
Please Sign up or sign in to vote.
An attempt to taking up an existing published article “C#.NET Interoperability with Native C Libraries on Cross Platform” towards the next level.


This tip is all about how to manage C#.NET framework interoperability at the cross platform level when the C#.NET application needs to be portable on Windows as well as Linux. This time, I am discussing on a somewhat more advanced level than my previous tip: C#.NET Interoperability with Native C Libraries on Cross Platform: PART I”.


In Part I, I demonstrated how to write C# code for interoperability with native C libraries to make it portable at the code level. It means we need to have separate builds for each platform. So for two platforms, we will have two C# executables, one for the Windows platform and the second for the Unix platform (even though the codebase is the same but having different compile time platform specific switches that makes the difference).

In this discussion, we are demonstrating how to make a single C# executable for Interoperability with Native 'C' call on cross platform to support Windows and Unix operating systems . It is very much tested on WinXP Service Pack-3 as well as on Debian Ubuntu 11.04.

Note: ‘C’ Native libraries will be platform-specific and same built library cannot be used for both the platforms, i.e., Windows and Linux. It means for each platform, 'C' library needs to be built explicitly which is inevitable .

Using the Code

There are two parts of this post. The first one focuses on the C Native Libraries code to make it portable at code build level. Please visit the previous tip PART-I to get C Native Library code and how to build on Windows as well as Linux. After building (Compiling & Linking), we will get libctest.dll on Windows and on Linux. For a quick native C Library build, unzip NativeCLib and open NativeTestLib.sln in MS Visual Studio on Windows and for Linux run located in the same folder of source.c file.

Second part is C# code, which is very different compared to Part I. Please have a look.

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

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Reflection;
namespace UseSharedObject
        // Generic Extension for all classes to invoke member functions on multi-platform :-)
        public static class MethodInvoker
            public static void InvokeMethod(this object main, 
            string strMethodName, Object[] parameters, ref object retObj)
                if ("Unix" == Environment.OSVersion.Platform.ToString())
                    strMethodName = strMethodName + "Ux";
                else // it is running on Windows OS                {
                    strMethodName = strMethodName + "Win";
                MethodInfo info = main.GetType().GetMethod(strMethodName); 
                if(info != null) info.Invoke(retObj, parameters);
        public struct Temp
            public IntPtr m_iVal;
            public string m_strVal;
        public class MainClass
                //Import ctestFillStructure
               [DllImport ("./assembly/", EntryPoint="ctestFillStructure")]
                public static extern void ctestFillStructureUx(out Temp i); //For Unix
               [DllImport("./assembly/libctest.dll", EntryPoint = "ctestFillStructure")]
                public static extern void ctestFillStructureWin(out Temp i); //For Windows
                //Import FreeResource
                [DllImport("./assembly/", EntryPoint = "FreeResource")]
                public static extern void FreeResourceUx(IntPtr ptr); //For Unix
                [DllImport("./assembly/libctest.dll", EntryPoint = "FreeResource")]
                public static extern void FreeResourceWin(IntPtr ptr); //For Windows
            public static void Main(string[] args)
                MainClass MyClass = new MainClass();
                object retValue=null;
                ("----------------------------- DEMO STARTS ----------------------------- \n");
                Console.WriteLine(" CALL 'C' LIBRARY FUNCTION, RETURN VALUES AS FOLLOWS");
                object[] arguments = new object[1];
                Temp valTemp;
                //Equivalent to ctestFillStructure(ref valTemp) 
                //but it checks runtime which method to be called based on current platform
                MyClass.InvokeMethod("ctestFillStructure", arguments, ref retValue); 
                valTemp = (Temp) arguments[0];
                Console.WriteLine("\t   valTemp.m_iVal = {0} valTemp.m_strVal = {1} 
                \n", Marshal.ReadInt32(valTemp.m_iVal), valTemp.m_strVal);
                //Equivalent to FreeResourceWin((IntPtr)(valTemp.m_iVal));
                //but it checks runtime which method to be called based on current platform
                Console.WriteLine(" FREEING RESOURCE WHICH WAS ALLOCATED BY 'C' LIBRARY \n ");
                MyClass.InvokeMethod("FreeResource", new object[] { valTemp.m_iVal }, ref retValue);
                valTemp.m_iVal = (IntPtr)0;
                Console.WriteLine(" CURRENT  PLATFORM = {0} 
                \n", Environment.OSVersion.Platform.ToString());
                ("----------------------------- DEMO ENDS ----------------------------- \n");
        }//Ends class MainClass
}//Ends namespace UseSharedObject

Declare DllImport for each imported 'C' function and for each platform, i.e., Win and Unix by passing library name and EntryPoint with C native function name followed by Ux and Win word to associate function call to the target platform. Later, it will be used by C# managed code to invoke native 'C' calls . Also define equivalent Temp structure in C# similar to Temp structure in C Library so it can be passed as a parameter.

To identify run time which method to be called based on the current platform, we need the MethodInvoker generic C# extension. To call ‘C’ Native function calls, the InvokeMethod extension call will be used which will take the C function name, the array of the passed parameter and the return value.

new object[] { valTemp.m_iVal }, ref retValue);

Copy the above generated and libctest.dll in the assembly folder on the same path of the UseSharedObject .NET executable.

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

Points of Interest

To make a C# generic extension to be supported to all classes, please pass the first parameter of type this object.

public static void InvokeMethod
(this object main, string strMethodName, Object[] parameters, ref object retObj)


  • This is the second draft version.


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.

You may also be interested in...


Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.170813.1 | Last Updated 18 Jan 2014
Article Copyright 2014 by deepi2014
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid