Rss

Archives for : February2011

Switchfoot Sydney Presale Password

… is HELLO. Presale’s over, though general admission tickets are still available at the time of writing.

Concert is at Luna Park Big Top, 21st of April 2011. Go buy your tickets now!


21st has been and gone, and it was awesome. New Empire, the pre-show act, was pretty good (better than I was expecting,) definitely going to check them out.

Pass-By-Reference from C# to C++

Whilst pass-by-reference isn’t generally used much in pure C# programming, when you’re working with a combination of C# and C++ and the number of returnable types are limited (generally you can only return simple data types,) it can come in useful when you need to return more than one value.

This is relatively quite simple, though first you need to be all setup for communicating from C# to C++. If you haven’t already, please read my blog post Calling C++ functions in C#, and passing arrays to get up to speed. Once you have a C# and C++ program setup that can pass by reference, you’re all set to continue.

Quite simply, it all comes down to the “ref” keyword in C#. Quite simply, if you are referencing a C++ function that has a value that’s pass by reference, then when you’re declaring the reference to it, put the word “ref” in-front of it. For example

C++ Code

void MyFunction(int & myInteger){     myInteger = 100;}

C# Code

[DllImport(“ImportDLL.dll”)]
public static extern void MyFunction(ref myInteger);

That’s pretty much it. The only other thing to bear in mind is that when calling MyFunction from the C# side, you must put the word ref infront. It’s pretty much so you don’t accidentally pass anything by reference if you don’t intend to.

C# Code

class Program
{
    [DllImport(“ImportDLL.dll”)]
    public static extern void MyFunction(ref myInteger);
    static void Main(string[] args)
    {
        int TheIntergerToPass = 50;
        MyFunction(ref TheIntegerToPass);
        Console.WriteLine(TheIntegerToPass.ToString());
    }
}

If the above code was teamed up with a program that included the above C++ code, then the output of the C# program would be 100, not 50, because the C++ program changed the value of the variable.

Do remember that the code listed isn’t fully functional as is: the C# code needs to have all the “using” definitions at the top, and the C++ code will need to have the functions prototyped with extern “C”. See the post that I mentioned before on how to set this up.

Calling C++ functions in C#, and passing arrays.

I thought I’d share this with the world in the form of a step by step guide (not to mention a good reference for myself,) as I just spent pretty much a whole day trying to figure this out.

The first part, just simply calling a function, isn’t terribly difficult. I had that under way without any problem. Passing variables was just as easy, it was how you would normally do it. What really stumped me was passing arrays across. I don’t really have too much of a problem with pointers, but pointers in a language that doesn’t have real good/safe pointer support is a bit different.

All the information presented here is online somewhere, it’s just I couldn’t already find a guide to do exactly what I wanted. There is quite possibly already one out there, and if so, the more guides the better.

Step 1: C++ function
Alter your C++ functions to expose their functionality. You do this by adding extern “C” to your header file, and putting all the prototypes of the exposed functions between { and }’s afterwards. For example.

main.cpp

#include “main.h”
int ReturnInteger()
{
    return 50;
}

main.h

extern “C”
{
    int ReturnInteger();
}

Compile that into a DLL.

Step 2: C# function
Put the generated DLL file in the same output directory as the C# output (so bin/Debug or bin/Release). In your C# project, be sure to include the following.

using System.Runtime.InteropServices;

In my console application, I made a static class that has all the references to my C++ DLL file. The class I put together looks like this:

static class CPPDLL
    {
        [DllImport(“ExternalLibrary.dll”)]
        public static extern int ReturnInteger();
    }

Simple, but effective. public static extern you pretty much want for all the functions. You may want to make them private it is only going to be called from within that class, which may happen later when we look at arrays.

My entire C# console application looks like this:

program.cs (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace InteropExample
{
    static class CPPDLL
    {
        [DllImport(“ExternalLibrary.dll”)]
        public static extern int ReturnInteger();
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(CPPDLL.ReturnInteger().ToString());
            Console.ReadLine();
        }
    }
}


That will, now, print out 50, and as we know that 50 is coming from the C++ library.
Step 3: Passing Values
Passing values works pretty much as you would expect. Simple data types are supported, and it’s probably best to stick to simple ones. And even better, when you declare CallingConvention = CallingConvention.Cdecl in your DllImport, you can use the C# string data type for char*.
main.cpp (C++)
#include “main.h”
int ReturnInteger()
{
    return 50;
}
char* ReturnString(char* input)
{
    return input;
}


main.h (C++)
extern “C”
{
    int ReturnInteger();
    char* ReturnString(char* input);
}

program.cs (C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace InteropExample
{
    static class CPPDLL
    {
        const string ImportLibrary = “ExternalLibrary.dll”;
        [DllImport(ImportLibrary)]
        public static extern int ReturnInteger();
        [DllImport(ImportLibrary, CallingConvention = CallingConvention.Cdecl)]
        public static extern string ReturnString(string input);
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(CPPDLL.ReturnInteger().ToString());
            Console.WriteLine(CPPDLL.ReturnString(“Hello from C# to C++ and back to C#”));
            Console.ReadLine();
        }
    }
}

Step 4: Getting Int arrays back
To me, this is what was the hardest part of the puzzle. Dealing with pointers in C# seemed annoying at first, and whilst it doesn’t seem like the most elegant way, it actually works out quite nicely. What you need is Marshal.Copy().

The best way to learn is by example, so below is the code that I put in the CPPDLL class

program.cs (C#)

static class CPPDLL
    {
        [DllImport(“ExternalLibrary.dll”)]
        private static extern IntPtr ReturnIntArray();
        public static int[] ReturnIntArray(int length)
        {
            int[] ReturnArray = new int[length];
            Marshal.Copy(ReturnIntArray(), ReturnArray, 0, length);
            return ReturnArray;
        }
}

You need to define the private function, and then a public static function. There isn’t too much to explain here really, but basically what the private function does is return a pointer, and then the public function get’s the pointer, put’s the values into an array, and then returns it. You do need to know how long the array is going to be before hand though, and pass the length to it. You can hard code the length in if the length of that array is going to remain static.

The corresponding C++ code is as follows:

main.cpp (C++)

#include “main.h”
int* ReturnIntArray()
{
    static int myArray[5] = {1, 2, 3, 4, 5};
    return myArray;
}

main.h (C++)

extern “C”
{
    int* ReturnIntArray();
}

You can now pass integer arrays back. Now, the most one I had most difficulty with… returning an array of strings.

Step 5: Getting back string arrays
I’m not going to go into too much detail with this one, other than to simply post the code. It’s fairly straight forward to work out if you understood all of the previous code.

main.cpp (C++)

#include “main.h”
char** ReturnStringArray()
{
    static char* myArray[3] = {“A1”, “BB2”, “CC3”,};
    return myArray;
}

main.h (C++)

extern “C”
{
    char** ReturnStringArray();
}

program.cs (C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace InteropExample
{
    static class CPPDLL
    {
        [DllImport(“ExternalLibrary.dll”)]
        private static extern IntPtr ReturnStringArray();
        public static string[] ReturnStringArray(int length)
        {
            string[] ReturnArray = new string[length];
            for (int j = 0; j < length; j++)
                ReturnArray[j] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(ReturnStringArray(), 4 * j));
            return ReturnArray;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            string[] myArray = CPPDLL.ReturnStringArray(3);
            foreach (string item in myArray)
                Console.WriteLine(item);
            Console.ReadLine();
        }
    }
}



So, there you have it, calling unmanaged C++ functions from within C#, and passing data from one to another! Obviously, it is preferable to have everything in the same language/platform (with .NET it doesn’t really matter what language it’s in,) but sometimes to re-write a C++ library would take hundreds of man hours, and writing a C# wrapper can take about an hour or so.

Download Source Code
The environment I used is Visual Studio 2010 for C# (C# Express should also work), and CodeBlocks 10.05 for C++.

Download entire source code.
    InteropExample is C#
    ExternalLibrary is C++

You will need 7-zip to extract the files.

References
All this post is, is a combination of all the different sources that I found, and my implementation of what they suggest. I couldn’t find a website or posting that solves this specific problem, but as I mentioned before, there could easily be one that I haven’t found. So, cheers to the people who originally made the content that helped me get this together.