This manual gives you a walk-through on how to use the Chemaxon .NET API.
All of the chemical knowledge of Chemaxon is written in Java. To make it available in .NET applications, a third party tool, called IKVM was used till the Iodine LTS release (September, 2021). IKVM can translate Java bytecode to .NET Intermediate Language (.NET IL) but it supports 8 or lower versions of Java only. In October 2021, Chemaxon switched to Java 11 so a new solution had to be implemented for the .NET -> Java interaction. The Java Native Interface (JNI) technology was selected for this task in the new Chemaxon .NET API.
Please note that the reconstruction of the .NET API focused on Chemaxon .NET API. Although several classes are available from JChem .NET, not all methods in all of these classes are implemented. As a long term plan, we would like to provide all Java classes in JChem .NET that is used by our clients (to avoid major changes in the integration codes), but at the moment, only a selected subset is supported. Please contact us if you miss a method in your integration code or even add your own wrapper implementation to your project. For help in doing so see the Tips and tricks for JChem .NET API users section.
The wrapper classes are the basis of the new JNI-based solution. Wrapper classes have to be implemented for all the used Java classes to make those callable in .NET code. Under the frame of the first version of the New Chemaxon .NET API, the focus was on the classes that are used in JChem for Office and were available in the old Chemaxon .NET API. These classes are wrapped, but a lot of other classes in JChem .NET API (related to JChem, Marvin, Calculator Plugins, etc. products) are still missing. As a future plan, we would like to provide all of the wrapper classes of the JChem .NET API used by our clients.
The new Chemaxon .NET API requires the same ChemAxon .NET API license as before.
There are 3 new DLLs in the JNI-based Chemaxon .NET API:
Java.JNI.dll
ChemAxon.JNI.dll
ChemAxon.Com.JNI.dll
These DLLs are responsible for the communication to the Java Virtual Machine (JVM) and these assemblies contain the wrapper classes for the Chemaxon .NET API.
The original 4 DLLs of the Chemaxon .NET API are also available and required to be referred in a .NET application:
ChemAxon.NET.Base.dll
ChemAxon.IKVM.dll
ChemAxon.Windows.Forms.dll
ChemAxon.NET.dll
MarvinEditorControl and MarvinSkecthForm do not work in the JNI-based Chemaxon .NET API. The new similar implementation is the MarvinSketchJFrame form. The following example illustrates the initialization and the usage of it. Please note this form is not modal.
IMarvinEditorView marvinEditor = new MarvinSketchJFrame();
// Marvin editor does not read/write the marvin.properties file
// in the user home folder "C:\Users\user name\chemaxon\" ...
marvinEditor.LoadMarvinProperties = false;
marvinEditor.SaveMarvinProperties = false;
// ... but uses custom settings.
StructureDrawingInfo drawingInfo = new StructureDrawingInfo();
drawingInfo.StructureDrawingSettings.ImplicitHydrogens = ImplicitHydrogenLabelOption.All;
drawingInfo.StructureDrawingSettings.RSLabels = RSLabelOption.AllPossible;
marvinEditor.StructureDrawingSettings = drawingInfo.StructureDrawingSettings;
// A molecule is loaded into the Marvin editor.
IJChemMolecule molecule = MainFactory.Chemistry.CreateMolecule("CC(=O)OC1=CC=CC=C1C(O)=O");
marvinEditor.MoleculeData = molecule.MoleculeData;
// The Marvin editor is shown.
if (marvinEditor.ShowAsDialog() == DialogResponse.OK)
{
// Gets the edited molecule object.
IJChemMolecule resultMolecule = MainFactory.Chemistry.CreateMolecule(marvinEditor.MoleculeData);
// A logS calculation on it (pH=7.4).
double logS = resultMolecule.Calculations.GetlogS(7.4);
// The rendering of it as a PNG image.
resultMolecule.Renderer.Settings.DrawingInfo.Size = new Size(210, 150);
resultMolecule.Renderer.Settings.DrawingInfo.Transparent = false;
resultMolecule.Renderer.Settings.DrawingInfo.BackgroundColor = Color.White;
Image image = resultMolecule.Renderer.RenderToImage(ImageFormat.Png);
}
The jre folder contains the Java runtime environments. There are a 32-bit (jre32.zip) and a 64-bit (jre64.zip) version of it.
Chemaxon's chemical knowledge written in Java is in the lib folder as jar files.
The bin folder contains the Chemaxon .NET API DLLs and its third party references for the custom .NET applications. The main assemblies that have to be referred in a .NET project are the follows:
ChemAxon.NET.Base.dll
ChemAxon.NET.IKVM.dll
ChemAxon.NET.Windows.Forms.dll
ChemAxon.NET.dll
Java.JNI.dll
ChemAxon.JNI.dll
ChemAxon.Com.JNI.dll
Unzip the zip packages in the jre folder then rename the jre32 subfolder to "x86" and the jre64 to "x64". Both have to have jvm.dll in it:
\jre\x64\bin\server\jvm.dll
\jre\x86\bin\client\jvm.dll
If the jre or the lib folder has a different location relative to the bin folder then these directory paths have to be stored in the Java.JNI.dll.config file.
For example:
<add key="JREPath" value="C:\Chemaxon\Java11\jre" />
<add key="LibPath" value="C:\Chemaxon\Iodine.4\lib" />
The initial and the maximum memory allocation pool for the Java Virtual Machine (JVM) can be set in the Java.JNI.dll.config file.
Initial memory allocation pool (Xms): <add key="Xms" value="512" />
Maximum memory allocation pool (Xmx): <add key="Xmx" value="1024" />
By default these values mean megabytes [m/M] but kilobytes [k/K] or gigabytes [g/G] also can be used. For example:
<add key="Xms" value="1024m" />
<add key="Xmx" value="2G" />
When implementing multithreaded applications using the new, JNI-based Chemaxon .NET API, an asynchronous code block that is expected to run on different thread(s) must be passed to the method JavaNativeInterface.ExecuteAsAsync as an Action/Function.
As the first step, the entry point to Java Native Interface is to be obtained by calling JavaNativeInterfaceFactory.GetJavaNativeInterface.
var javaNativeInterface = JavaNativeInterfaceFactory.GetJavaNativeInterface();
The method ExecuteAsAsync must be used for all code blocks that are expected to run on different threads (note that the thread can also be the “main” thread, which was used upon the creation of JavaNativeInterface):
var thread = new Thread(() =>
{
javaNativeInterface.ExecuteAsAsync(() =>
{
// Code with calls to ChemAxon.NET, running on this thread
});
});
Parallel.ForEach(molecules, molecule =>
{
javaNativeInterface.ExecuteAsAsync(() =>
{
// Code with calls to ChemAxon.NET,
// running on threads created by Parallel.ForEach
});
});
var t = Task.Run(() =>
{
javaNativeInterface.ExecuteAsAsync(() =>
{
// Code with calls to ChemAxon.NET,
// running on thread created by Task.Run
});
});
Callbacks aren’t implemented yet. It is not possible to subscribe to Listener interfaces, nor to PropertyChangeListeners.
MarvinSketchJFrame.ShowAsDialog method polls the state of the displayed Marvin editor control to be notified when the window is closed for obtaining the edited molecule. This is handled transparently.
Marvin OLE Server has been removed from Chemaxon .NET API. It will not be available in the next JNI-based JChem for Office releases either. Thus, copying, pasting or editing Marvin OLE objects will not be available in the future.
IOleHandler interface and its implementation has been removed, and is not available in the New Chemaxon .NET API.
Missing wrapper classes or methods can be added manually to a .NET application for extending the JChem .NET API. Furthermore, all of the wrapped Java functions are virtual in the JChem .NET API so these can be overwritten easily.
References:
For standard Java classes
For JChem classes
Important note: added classes have to have the same namespaces as the original classes have. For example the QueryBond classes are missing in the new .NET API. It can be added to a custom .NET application but it has to be under the namespace chemaxon.struc. So the full qualified name of the class has to be chemaxon.struc.QueryBond.
Example of usage
Extending a class:
/// <summary>
/// Extension of the chemaxon.struc.MolBond class.
/// </summary>
public class MolBondExt : MolBond
{
...
}
Extending a custom class:
/// <summary>
/// A java.util.Map implementation.
/// </summary>
/// <typeparam name="K"></typeparam>
/// <typeparam name="V"></typeparam>
public class JniMapExt<K, V> : java.util.JniMap<K, V>
{
...
}
Adding a missing constructor:
/// <summary>
/// Construct a query bond between two atoms.
/// </summary>
/// <param name="a1"></param>
/// <param name="a2"></param>
/// <param name="s"></param>
public QueryBond(MolAtom a1, MolAtom a2, string s)
: base()
{
MethodBase methodBase = MethodBase.GetCurrentMethod();
string javaClassName = JavaNativeInterface.GetJavaClassName(methodBase.DeclaringType);
string signature = JavaNativeInterface.GetSignature(methodBase, a1, a2, s);
InitializeJavaClass(javaClassName);
InitializeJavaObject(signature, a1, a2, s);
}
Adding a copy constructor:
/// <summary>
/// Copy constructor.
/// It copies the original chemaxon.struc.MolBond object by its Java object.
/// </summary>
/// <param name="bond"></param>
public MolBondExt(MolBond bond)
: base(bond.JavaObject)
{
}
Implementing a void function:
/// <summary>
/// Sets the query string.
/// </summary>
/// <param name="s"></param>
public void setQuerystr(string s)
{
this.CallVoidMethod(MethodBase.GetCurrentMethod(), s);
}
Implementing a non-void function:
/// <summary>
/// Checks if two bonds have the same properties.
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public bool haveEqualProperties(MolBond e)
{
return this.CallMethod<bool>(MethodBase.GetCurrentMethod(), e);
}
Implementing a static function:
/// <summary>
/// Returns the enum constant of this type with the specified name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static ClientInfoStatus valueOf(string name)
{
return JavaNativeInterface.CallStaticMethod<ClientInfoStatus>(MethodBase.GetCurrentMethod(), name);
}
Overwriting a non-virtual function:
/// <summary>
/// Overwrites the clone function.
/// </summary>
/// <returns></returns>
public new object clone()
{
return this.CallMethod<object>(MethodBase.GetCurrentMethod());
}