Monday, 15 December 2008

Mono, C# and OpenBabel

Matt Sprague and I have put in a bit of work making OpenBabel accessible on the .NET platform on Windows (see Matt's recent post, for example). .NET is like Microsoft's JVM. There are several .NET languages (e.g. C#, Visual Basic, IronPython), just like there are several languages for the JVM (e.g. Java, Jython, JRuby). If you write a program in any of the languages and compile it, the resulting classes can be used from any of the other languages.

Having finished the work for Windows, I started to look at Linux and MacOSX. There's an Open Source version of .NET called Mono, which is available cross-platform. After a bit of hacking around, I'm pleased to announce that the next release of OpenBabel will provide support for Mono on Linux and MacOSX. I've included an example C# and IronPython script that uses OpenBabel (see here).

One thing I was wondering though: anyone have any idea how widely Mono is used?


Joerg Kurt Wegner said...

Noel, this is *highly* valuable for people using C#. Is the .NET binding already readily available? I would like to use it right-away ;-)

I am specifically interested in creating a SMARTS filter.

baoilleach said...

Yes - it's already available, see

I have been keeping a bit quiet about it as it was still under development and I was waiting for OB2.2.1 for a final release. If you do try it, we'd appreciate some feedback.

mesprague said...

Developers who are interested in OBDotNet might also want to check out ChemSharp

the project which provided the impetus for OBDotNet. We're still in the very early phases of development of what we hope will eventually be a of a purely managed C# cheminformatics library. We would welcome any input from people currently using CLI languages in their work.

James Jack said...

I'm getting an error when using OBDotNet in a winforms app in Visual Studio 2008.

Anyone seen this or know how to fix?

The error occurs when I try to create a new OBConversion object:

private void button1_Click(object sender, EventArgs e)
OBConversion obconv = new OBConversion();
OBMol mol = new OBMol();
obconv.ReadString(mol, "CCC");

Here's the full error:

System.TypeInitializationException was unhandled
Message="The type initializer for 'OpenBabel.openbabelcsharpPINVOKE' threw an exception."
at OpenBabel.openbabelcsharpPINVOKE.new_OBConversion__SWIG_2()
at OpenBabel.OBConversion..ctor()
at OBTest.Form1.button1_Click(Object sender, EventArgs e) in C:\Users\James\Documents\Visual Studio 2008\Projects\OBTest\OBTest\Form1.cs:line 21
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at OBTest.Program.Main() in C:\Users\James\Documents\Visual Studio 2008\Projects\OBTest\OBTest\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.TypeInitializationException
Message="The type initializer for 'SWIGExceptionHelper' threw an exception."
at OpenBabel.openbabelcsharpPINVOKE.SWIGExceptionHelper..ctor()
at OpenBabel.openbabelcsharpPINVOKE..cctor()
InnerException: System.BadImageFormatException
Message="An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)"
at OpenBabel.openbabelcsharpPINVOKE.SWIGExceptionHelper.SWIGRegisterExceptionCallbacks_openbabelcsharp(ExceptionDelegate applicationDelegate, ExceptionDelegate arithmeticDelegate, ExceptionDelegate divideByZeroDelegate, ExceptionDelegate indexOutOfRangeDelegate, ExceptionDelegate invalidCastDelegate, ExceptionDelegate invalidOperationDelegate, ExceptionDelegate ioDelegate, ExceptionDelegate nullReferenceDelegate, ExceptionDelegate outOfMemoryDelegate, ExceptionDelegate overflowDelegate, ExceptionDelegate systemExceptionDelegate)
at OpenBabel.openbabelcsharpPINVOKE.SWIGExceptionHelper..cctor()

James Jack said...

OK - I found the problem.

My machine is rinning WIndows 7 64 bit and was trying to use the OBDotNet libs in 64 bit mode. I Changed the compiler option to x86 and it now works.

Very Cool!

baoilleach said...

@James: Phew - I'm glad you figured it out. I'll keep a 64-bit build in mind for future releases (I'm still running XP myself). BTW, I'm interested to see what you come up with and also whether you have any suggestions for improvements.

James Jack said...

Ok - this weekend I made an OpenBabel addin for Symyx Draw. When I'm done testing I'll post the code. The .net interface works really well.

Anonymous said...

I'm also looking at a Symyx Draw addin to interface with MOPAC. I have a working prototype, but there seems to be some problems...

I'm using OBDotNet to convert my molfile in Symyx Draw to a cartesian MOP file which I can then send to MOPAC.

I can't seem to get OBDotNet to use the "h" option for adding hydrogens at open valences (I hope that is what it's supposed to do). Does anyone have some example C# or VB.Net code with the syntax to make options like "h" work? I tried various ways (SetOption, AddOption, IsOption) but none seemed to work.

Mean time I used Symyx Cheshire to add H and can pass the resulting MOP to MOPAC, but post optimization the results of converting the MOPAC .out file back to a .mol give spurious results. Hydrogens and double bonds seem to move arround the resulting output at will. I must admit I'm new to MOPAC and OpenBabel, so the chances are I'm doing something wrong or making some incorrect assumptions.

Any advice? Both add-ins will be free and I will be publishing the source code so the community should benefit...

baoilleach said...

@James: An example of using SetOptions is at

Regarding MOPAC usage, you should probably email AFAIK, this is new code so feedback is very welcome.

James Jack said...

Is the "h" option is a general OpenBabel option as opposed to one for a specific file type? The SetOptions example you sent me suggests that its for the options specific to a file type. "h" is not an option for mop files.

I'll post this question as you suggest.

Charlie Zhu said...

I have met the same problem on Windows 7 x64. Thanks for your hint.

Charlie Zhu said...

And this recipe described clearly how to switch compile target to X86 in Viusal Studio Express edtion.

baoilleach said...

@Charlie: Thanks for the pointer, but it only works for MSVC#Express 2005 and not 2008 (and I'd prefer not to change the build system again right now). In a month or two I expect to have a Windows 7 machine which will hopefully allow me to build both 32 and 64-bit versions (?).

James Jack said...

I'm seeing an error with mopout files, both in the OpenBabel GUI and via OBdotNet:

private static string OBConvert(string inFormat, string outFormat, string inputMol)
var obconv = new OBConversion();
var mol = new OBMol();
obconv.ReadString(mol, inputMol); //<== Error here with valid mopout file
var outputMol = obconv.WriteString(mol);
return outputMol;

Anyone seen this? I submitted a bug report and I also found a similar bug report from several versions back. Could be a regression?