On the mixing of C, C++, C# and Lisp code

Every programmer once will have the impression that he is writing exactly the same code as he did a while ago, be it in another programming language. After a while, every programmer collects an extended library of small code snipsets in various programming languages. Therefore, it is very interesting to investigate how to combine code written in different languages into a single program.
In the overview given below, microsoft visual studio 2005 was used for the C,C++ and C# language and Allegro Common Lisp for the Lisp code.

In this document, we describe the following topics: Please note that this overview is very very basic. With several of the language combinations which are presented here, several highly complex issues need specific attention. Those are however beyond the scope of this overview.

Many other combinations of languages are very interesting and might be added in the future.

Creating a dll in C

We first make a dll containing some simple C code. Further on in the document, we will show how to call this C code from other languages.
extern "C"
{
  __declspec(dllexport) void DisplayHelloFromDLL()
  {
    printf ("Hello from DLL !\n");
  }
}
The above C code exports a single function, that is all we need to perform a first test.
Example project: cdll.zip

Creating a dll in C++

Similarly, we can export classes rather than single functions. In the header file of the class, simply add "__declspec(dllexport)" as shown below.
class __declspec(dllexport) Adder
{
	public:
		Adder(){;};
		~Adder(){;};
		int add(int x,int y);
};

Example project: cppdll.zip

Creating a dll in managed C++

As we can not call a simple plain C++ dll from C#, we will create a managed C++ dll here first.
#using <mscorlib.dll>
using namespace System;
using namespace System::Collections;

__gc public class Adder
{
	public:
		Adder(){;};
		~Adder(){;};
		int add(int x,int y);
};
Example project: managedcppdll.zip

Creating a dll in C#

In C# we create a class rather than a set of functions. This is interesting, now we could try to use the class, rather than single functions in another language.
namespace dlltest
{
    public class Adder
    {
        public int add(int x, int y)
        {
            return (x + y);
        }
    }
}
A simple adder class is created by the above code.
Example project: csdll.zip

Calling a C++ dll from C++

Calling a dll we made in C++ from C++ is also straightforward. If we want to call the C++ Adder class we defined above, we have to add a header file for the class and specify that this class is external.
class __declspec(dllimport) Adder
{
	public:
		Adder(){;};
		~Adder(){;};
		int add(int x,int y);
Once this header is added, we can use the adder class as if it was defined in the currect project. The only thing we have to do, is add the adderdll.lib file to the current project.
Example project: cppcallscppdll.zip

Calling a managed C++ dll from managed C++

The nice thing is that this can be accomplished without a header file declaring the class as external
#include <iostream>
#using <mscorlib.dll>

#using <cppdll.dll> // cppdll.dll is the name of the dll which contains the managed C++ code for the Adder class

using namespace System;
using namespace System::Collections;
using namespace std;

void main(void)
{
	Adder a;
	cout << a.add(3,5) << endl;
	while(1);
}

Example project: mancppcallsmancppdll.zip

Calling a C# dll from managed C++

Now, the same thing with the C# dll rather than the C++ dll. Surprisingly, this requires one line to be changed, we now need to add a "using namespace ..." direction.
#include <iostream>
#using <mscorlib.dll>

#using <cppdll.dll> // dlltest.dll is the name of the dll which contains the C# code for the Adder class

using namespace System;
using namespace System::Collections;
using namespace std;

void main(void)
{
	Adder a;
	cout << a.add(3,5) << endl;
	while(1);
}

Example project: mancppcallscsdll.zip

Calling a C dll from C#

Calling the dll we made in C from C# is very very easy, check out the few lines of code below
using System.Runtime.InteropServices;

namespace Dllcaller
{
    class Program
    {
        // cdll.dll is a C-style dll which exports the DisplayFromDll function!
        [DllImport("D://cdll.dll")]
        public static extern void DisplayHelloFromDLL ();      

        static void Main(string[] args)
        {
            DisplayHelloFromDLL();  
        }
    }
}
Example project: cscallscdll.zip

Calling a C# dll from C#

Also this is very easy. Now we have to take care to add the dll which we will use to the references of the C# project. Once that is done, the Adder class we defined in the C# dll can be used without any problem.
using dlltest;

namespace Dllcaller
{
    class Program
    {
       	// the adder class is defined in the C# dll.
        static void Main(string[] args)
        {
            Adder a = new Adder();
            Console.WriteLine(a.add(1, 2));
        }
    }
}
Example project: cscallscsdll.zip

Calling a C++ dll from C#

the C# code shown below can be used to call the C++ managed Adder class.
using System;
using System.Collections.Generic;
using System.Text;

namespace Dllcaller
{
    class Program
    {
        static void Main(string[] args)
        {
            Adder a = new Adder();
            Console.WriteLine(a.add(1, 7));
            while (true) ;
        }
    }
}
Example project: cscallscppdll.zip

Calling a C dll from Lisp

From Allegro Common Lisp, one can call C functions without any problem. As we do not have a console output available in ACL, the C dll we defined earlier in this document, is not of much use. We therefore add the following function to the C dll.
  __declspec(dllexport) int add(int x,int y)
  {
	  return (x + y);
  }
The add function from C can be called easily is LISP. See below.
(use-package 'ff)

(load "D:/opencv/code/dlltestcode/cdll/debug/cdll.dll")

(def-foreign-call (add "add")((x :int)(y :int)) :returning :int)

(add 3 5)