Calling C# from C++

Most of the post on the internet about interoperability is the other way around (Calling C++ from C#) since C# is apparently the superior language in terms of developer friendliness. But a part of research work is to make weird combinations of system work regardless of the reason.

I succeeded in doing just that thank to this Visual C++ example (documentation is available in part 1 of the tutorial).

One thing to add is, I needed a tool to export .NET 4.0 to .tlb files so I can use the same assemblies in C++ (pure C++ and not C++.NET). The tool is called tlbgen, and the syntax is quite simple:

tlbgen System.Net.dll

Building WS4D-gSOAP on Linux

WS4D-gSOAP is a framework that assists development of web services on multiple platforms. These includes mobile phones, server, computers or embedded system.

WS4D Features

WS4D can run as a standalone application or based upon a server and has been used in many commercial products. Despite being the most prominent framework for embedded system SOAP services, WS4D seems to be lacking behind in version support and documentation. Namely, you cannot build the latest version of WS4D-gSOAP with the latest version of gSOAP, even though both frameworks’ last version were one or two years ago. Development doesn’t seem to be active, so does the community. Finding help is a big hassle!

So, this post outlines some problems i encountered while working with the framework and how to solve them, hoping that the next follower won’t have as much trouble starting in a new environment.

Terminology

It seems that the WS4D documentation assumes that you have a certain level of understanding on Unix-based build system and working across platform. You cannot find definition for several new terminologies used in the documentation, so the docs may be quite confusing and intimidating for new users. I find these words particularly weird:

  • In source build: The binaries will be generated inside the same directory as the source. This has the advantage of simplifying the make files as you don’t have to link and copy libraries over, but the directory may look extremely messy.
  • Out-of-source build: Separate source and binary directories. This is the configuration used by WS4D tutorial and code. The sample make file in the tutorial already to the hard work and creates the most common directories used in almost all WS4D projects.
  • Cross-compile (and compilation): This means instead of compiling only one binary to use on your development platform, it will compile another binary for another platform. What do you do with this second binary is up to you: you can push it to the device or run it in a simulator, but cmake’s job in this case is only generating the binary file for you.
  • Tool-chain: A set of compiler and linker for a specific device or platform. Cross-compiling uses two or more tool-chain to generate two or more executable.

Proper version

The documentation for WS4D is a bit disorganized, so it may not relevant for first-time readers that you must compile WS4D with specific versions of gSOAP, doing otherwise will lead to make-errors and build headaches. It is mentioned in Features page (which is not visible from the first page of documentation). I was reading only the installation instruction and tutorial when I started to build the system, so I missed this important fact! How should I know that Getting Started is not a good place to get started?

ws4d-gsoap 0.7.x ws4d-gsoap 0.8.x ws4d-gsoap trunk
 gSOAP 2.8.0 Not yet supported Not yet supported Not yet supported
 gSOAP 2.7.17 Not yet supported supported with patch supported with patch
 gSOAP 2.7.16 Not yet supported supported with patch supported with patch
 gSOAP 2.7.15 Not yet supported Not yet supported Not yet supported
 gSOAP 2.7.14 Not yet supported Not yet supported Not yet supported
 gSOAP 2.7.13 supported supported supported
 gSOAP 2.7.12 supported supported supported
 gSOAP 2.7.11 supported supported supported
 gSOAP 2.7.10 supported supported supported

So the latest version of the stack you can use is gSOAP 2.7.17 with WS4D-gSOAP 0.8. I don’t know why it is so complicated, maybe due to the fact the gSOAP 2.8 also implemented WS-Discovery (a feature overlap with WS4D), and the auther didn’t have enough time to adjust WS4D-gSOAP to the new changes.

Build steps and permissions

Supposed you have decent Linux knowledge, you can use this inside the directory where WS4D-gSOAP was extracted to

  1. ./configure
  2. ccmake .
  3. Edit path to gSOAP directory (the source you downloaded, do not ‘make install’ this)
  4. Press g to generate, there may by some warning, ignore them
  5. Press c to configure
  6. make (I don’t know why this step is needed, but if you misses this step, the next step will result in various errors. This step will result in errors)
  7. su -c ‘make’ – (You can’t use sudo, you have to use su with a trialing dash to load root user’s environment. Root permission is required to install binaries to their proper locations)

Web service for device (WS4D) and using make, cmake with Integrated Development Environments (IDEs) on Linux

WS4D-gSOAP is a framework to deploy web services on multiple environments (computers, embedded devices, phones…) without having to rewrite code. More introduction information can be found in this post. The downside for WS4D is that the build system is based on cmake, and it’s a bit complicated to use. I have since managed to successfully build the stack from source (there’s no binary distribution). But I ran into numerous problems during my time getting familiar with the stack. Namely following the tutorial.

Even for such a simple task of copying and pasting code from the tutorial (The Air Conditioner tutorial), I did not succeed. The client and device doesn’t seem to be able to communicate with each other. Even though the tutorial have been kind enough to include logging code (send, received and memory allocations), I’m still unable to figure out where the problem lies. And that’s when I think I’m forced to perform debugging on the project. That leads to a big problem: what am I supposed to use to debug this?

So I tried to install Code Blocks, but it doesn’t support cmake projects, it couldn’t import the CMakeList.txt. Then reading through several articles revealed Eclipse to be a pretty good gdb front-end, I installed it, and have successfully imported the project, but I was hit with several problems:

  • I couldn’t build the project, Eclipse’s project structure was make-based, not cmake-based, trying to ‘make all’ or ‘make clean’ with Eclipse obviously would generate errors
  • Editing  the code is an eyesore because Eclipse doesn’t seem to be able to recognize include and libraries directories even after I added them manually in project properties.
After several more hours of analyzing WS4D-gSOAP documentation (not really helpful, they are only related to build and run with command line), cmake (wiki pages after wiki pages with no structure between pages and in articles), Eclipse and Code Blocks’ documentation on make projects; I finally realized the right way to do this: cmake supports generating make-based projects for both Code Blocks and Eclipse, and it’s as simple as this:
  1. Go to the directory where you would normally run cmake to build your project from the command line
  2. Perform

    cmake -G"Eclipse CDT4 - Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../certi_src
    cmake . -G "CodeBlocks - Unix Makefiles"
  3. Import

    The project directory
    ProjectName.cbp file
You can now work with the project normally within your preferred IDE

Why specifying the call type when performing P/Invoke is important

I was working on a C# project that required interaction between unmanaged and managed code. It’s nothing complex, just calling various functions in a DLL through a wrapper class, then I hit this exception:

A call to PInvoke function 'TestLPRLib!EvAPI.EvLicensePlateReg::evLPROpen' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

Strange thing is, this “stack unbalanced” exception only pop up when running in debug mode, the application still work just fine without debugging, but leave bugs in applications is not my habit, so I decided to reach out to Google. The unmanaged code used __declspec(dllexport) to specify exported functions, internet forums suggested this exception is caused by the difference in calling convention.

So, I changed the unmanaged code from

extern "C" __declspec(dllexport) int evLPROpen(int width, int height, int widthStep, int depth = 8, int channel = 3);

to

extern "C" __declspec(dllexport) int __cdecl evLPROpen(int width, int height, int widthStep, int depth = 8, int channel = 3);

And the wrapper from

[DllImport("LicensePlateRecognitionLib.dll")]
public static extern int evLPROpen(int width, int height, int widthStep, int depth, int channel);

to

[DllImport("LicensePlateRecognitionLib.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int evLPROpen(int width, int height, int widthStep, int depth, int channel);

(using the clear stack by caller convention), and the exception goes away. By default, .NET assumes you use __stdcall, but I didn’t have much success trying this 🙂

Scary Symbian

I’m not really in the mood to revise writing communication scripts… So I will just blog about Symbian to conclude the assignment I submitted yesterday.

Symbian started as a collaborative Effort between Nokia, Sony Erricson, Samsung and several other mobile phone manufacturers to create an operating system that work for their devices. It’s certainly not the first OS, Palm OS existed long before that. The fact that Symbian collaborated development started in 1998 and got wide attention around 2000 may make you expect a modern operating system with good design while maintaining compatibility.

It’s simply scary for me.

Looking at the sheer amount of features and headers would make you confused, the documentation seems to be machine – generated with very very very few example what each function do. It’s a good thing that a single operating system support all functionality that normally only available on separate devices: media player, digital camera, gaming device… But that is a burden for the developers :(. They will have to get familiar with a multitude of data structures… You think int is just int? No, for Symbian there are 8 bit int, 16 bit int and 32 bit int, and the developer will have to decide what to write both when they design (write the header) and when they code (using the function). Failing to match the two declaration can be fatal and that lead to debug…

To debug you’ll have to install Nokia’s tool: Carbide; which in turn will require you to install

  • Perl
  • Java
  • GNU C++
  • MingW in case you use Windows
  • Phone SDK for simulation; and they install a complete set of files for each SDK

Three languages just to program in one language for one operating system! Even so, if they worked smoothly then there weren’t this post: the SDK installation has a screen in which you can choose where to install, even though you can click the button and change it; and the documentation didn’t recommend otherwise, don’t change it. It will mess up with itself! Installing the SDK in a drive different from the IDE, or different from your workspace drive would results in dumb error messages like “file not found” which unless you are familiar with *nix system, you’ll just went mad! (And even if you have the skill to fix it, are you ready to fix tens of thousands of lines of Perl code just to write a C++ hello world!?)

Expecting the resource editor? It depends on whether you've been nice or naughty…

Expecting the resource editor? It depends on whether you've been nice or naughty…

If you have installed stuff on Windows Mobile before, and ever think to yourself “why must I bring my phone to phone shops, I can do this, piece of cake!”, try using Symbian! Each program throws resource in multiple directories, together with system applications. While this is a good thing on some aspects, a developer just can’t find where his resource file is in the big mess called “sys”. If you think Windows’s window directory on windows mobile is messy because it’s full of dll and executables, have a look at Symbian’s system directory. You’ll see types of files have never seen. Open your eyes and embrace r01, l01, mbm… And because the OS is that complex, OS’s native file structures is complex, to do something as simple as replacing a bitmap, the developer will have to wait for the tools to rebuild it, and then deploy it to the phone, which is not a fast process at all…

And possibly for the same reason why you must rely on shops when your phone has problem, the documentation doesn’t have any mention for any error and how to fix it… Sometimes if you are in luck you may found it in some corner of the Internet. For example a common problem for the 3rd SDK FP1 emulator is it display a kernel failure every time it start. If you google the error, you’ll see several discussion on forum nokia (and several copy of those discussion), most of which will tell you “leave it there, it doesn’t hurt”. It’s not until one beautiful day searching for another kernel problem that I found this KB article: NCNList KERN-EXEC 3 panic when starting the S60 3rd Edition, FP1 emulator. There you go, download the file, install it, and if your phone is happy, it won’t spit a list panic =))

Small community size, clueless forum posts is what you are going to face searching for help with Symbian. I wonder how could they able write so many stuff for their phone? Magic happens among Nokia-employed developers? =))

Some part in their documentation, they mention about how Symbian is so different from normal C, it was designed before the current C++ standards were born. Oh really? How come you can design a new interface for acceleration sensor and can’t even wrap the compiler to use the approrate kind of number and character instead of forcing the developers write clueless stuff like Tint, Tbuf, Tdes, TPtr!? C++ is complex enough already! Keep in mind that you inherited that together with the language next time! Or is it just too hard to let the compiler do exception handling the C++ way instead of some “simple leaves” which make the developer throws away most of their knowledge about constructors to do the so-called “2 phase contruction” like

CBanCo::CBanCo()
{
}
CBanCo::CBanCo(TRect aRect)
{
	iRect=aRect;
	iSize=15;
	iNum=0;
	TRgb color(102,255,255);
	iColor=color;
    iWidth = aRect.Width();
	iHeight = aRect.Height();
	iSwitch = EFalse;
}
void CBanCo::ConstructL()
{
	CSettings* settings = CSettings::NewL();

	iSize = settings->iBoardSize;
	iRow = iHeight/iSize;
	iCol = iWidth/iSize;
	iFlag = false;
	iColCur = iRowCur = 0;
	iArray = NULL; // The following line may fail
	iArray = new (ELeave) CArrayFixFlat(iRow*iCol);
		for(TInt i=0 ; i < iRow ; i++)
			for(TInt j=0 ; j < iCol ; j++)
				iArray->AppendL(-1);
	if (settings->iPlayerSymbol == 0)
		iSwitch = EFalse;
	else
		iSwitch = ETrue;
	iImageX = AknIconUtils::CreateIconL(BitmapStore, (iSwitch == EFalse? 2 : 3));
	iImageO = AknIconUtils::CreateIconL(BitmapStore, (iSwitch == EFalse? 3 : 2));

	delete settings;
}
CBanCo::~CBanCo()
{
	if (iArray != NULL)
		delete iArray;
	if (iImageX != NULL)
		delete iImageX;
	if (iImageO != NULL)
		delete iImageO;
	iArray = NULL;
	iImageX = NULL;
	iImageO = NULL;
}
CBanCo* CBanCo::NewL(TRect aRect)
{
	CBanCo* myObj = CBanCo::NewLC(aRect);
	CleanupStack::Pop(myObj);
	return myObj;
}
CBanCo* CBanCo::NewLC(TRect aRect)
{
	CBanCo* myObj = new (ELeave) CBanCo(aRect);
	CleanupStack::PushL(myObj);
	myObj->ConstructL();
	return myObj;
}

While it could be

CBanCo::CBanCo()
{
	;
}
CBanCo::CBanCo(TRect aRect)
{
	iRect=aRect;
	iSize=15;
	iNum=0;
	TRgb color(102,255,255);
	iColor=color;
    iWidth = aRect.Width();
	iHeight = aRect.Height();
	iSwitch = EFalse;
	CSettings* settings = new CSettings();
	iSize = settings->iBoardSize;
	iRow = iHeight/iSize;
	iCol = iWidth/iSize;
	iFlag = false;
	iColCur = iRowCur = 0;
	iArray = NULL; // The following line may fail
	iArray = new (ELeave) CArrayFixFlat(iRow*iCol);
		for(TInt i = 0; i < iRow ; i++)
			for(TInt j=0 ; j < iCol ; j++)
				iArray->AppendL(-1);
	if (settings->iPlayerSymbol == 0)
		iSwitch = EFalse;
	else
		iSwitch = ETrue;
	iImageX = AknIconUtils::CreateIconL(BitmapStore, (iSwitch == EFalse? 2 : 3));
	iImageO = AknIconUtils::CreateIconL(BitmapStore, (iSwitch == EFalse? 3 : 2));
	delete settings;
}
CBanCo::~CBanCo()
{
	if (iArray != NULL)
		delete iArray;
	if (iImageX != NULL)
		delete iImageX;
	if (iImageO != NULL)
		delete iImageO;
	iArray = NULL;
	iImageX = NULL;
	iImageO = NULL;
}

See it? my code hilighter can’t parse Symbian C++ as C++ :))… I stray too far from the debug part, didn’t I? Yes, the debugger does not allow code view, and because it stops immediately when some error happens, you can’t see the values you are tracking at that time. Proved you are clever enough to have the debug work while winscw’s configuration just won’t start.

Guess that when the phone is sold to the rich, its developers should also be rich and have a lot of spare time to think like the rich then. At least the OS have a nice interface after all

Symbian gomoku, thanks to my instructor

Symbian gomoku, thanks to my instructor

Strangely, I can’t help noticing Nokia still has the largest market share in the smartphone market according to canalysis (51% in 2007). I just can’t find a nice chart to match smartphone sales to dumb phone’s so I can’t just conclude that most of the rich people uses an inextricably complex operating system 😛

Nevertheless, iPhone is steadily gaining its part and the first dream phone (as what Google calls it) appeared a couple of months ago also with quite a lot of function. Both of which could be interesting factors to facilitate Symbian in the future.