Calling C# Methods from Sicstus Prolog through COM Interface

Written by on November 10, 2019 in Programming, Prolog with 0 Comments

Recently I needed to make use of a C# library (which I had implemented a few years ago) from Sicstus Prolog. Calling C/C++ functions from Sicstus Prolog is fairly well documented. When it comes to C#/.NET, the official documentation recommends the PrologBeans library. After going through the documentation, I felt that it would not work for me for the following two reasons:

1) This library requires Prolog to be the server and C#/.NET to be the client, and the primary communication is from the client to the server. But my requirement was the other way – calling C# from Prolog.

2) The server and client run as different processes. This can be useful when we need to build a scalable, heavy-weight client-server system, but it was “too heavy” for my requirements. I needed an in-process mechanism for the communication.

I looked around the documentation and found that the library comclient allows Sicstus Prolog to act as a COM client. This seemed like a workable solution; I have to provide a COM interface to my exisitng library and then it can be invoked from Sicstus Prolog. It is also an “in-process” interaction, and hence avoids inter-process communication overheads.

And that is what I ended up doing. It worked pretty well.

In this article, I wish to outline the process of implementing a simple COM object in C# and then show how to use it from Sicstus.

I am using Visual Studio 2019 Ver 16.3.7, so there could be some differences between the screens I have shown here and yours (if you have a different version). 

Step 1:

Make sure you launch Visual Studio in “Administrator Mode” (this is required for Step 4 to work). Create a new project of type “Class Library (.NET Framework)”. See the following image.

Creating a New Project

Creating a New Project

Step 2:

Give a suitable name for the project and select an appropriate directory to save the solution.

Step 3:

In the project’s “Build Settings”, enable “Register for COM Interop”. See below.

Enable COM Interop

Enable COM Interop

Step 4:

Another important step is to register the generated DLL for use as COM object through the “RegAsm” utility. Since this is done after the project is built, we can include this command in the “Post-build” step in the Project settings.

Registering the COM Object

Registering the COM Object

This applies to 64-bit DLL alone. The “/tlb” option is not needed in our case, but would be required if you are, for example, implementing a COM client in C++.

As I mentioned earlier, for this step to succeed, you must have started Visual Studio in “Administrator” mode.

Step 5:

Define the class that should act as the COM object (server). Make sure you include the “System.Runtime.InteropServices” Namespace. My example class is quite simple. It has just 4 methods as shown in the following image:

The COM Class

The COM Class in C#

The first method “add” starts with a lowercase letter, which is not the recommended convention. I did this deliberately and will explain the reason later.

The first two methods take two “int” arguments and return an “int”. The third method “Concat” takes two string args and returns a string.

The last method “ProcID” returns the ID of the currently running process. I will be using this to show that both the Sicstus Prolog engine and C# run in the same process.

In order to convert a class like this into a COM object, we have to decorate the class with additional attributes.

The class requires a unique GUID that will be used from the client. Generating this is quite easy in Visual Studio.

Select the “Create GUID” command from the “Tools” menu.

Generating GUID: Step 1

Creating GUID

This prompts you for the format of the GUID. Choose option (5):

Selecting GUID Format

Selecting GUID Format

Copy and paste the generated GUID in the GUID attribute of the class. Although ProgID attribute is not needed, I recommend it because this gives a readable name to the COM object. In the Prolog client, we can use either the GUID or the ProgID to connect to the COM object.

My build target is “x64” as the target CPU. The reason is my Sicstus Prolog is a 64-bit application running on Windows 10.

Step 6:

Build the project. Here is the output of the Build process:

Build Output

Build Output

Files “Server.dll” and “Server.tlb” would have been created. 

Using the COM Object from Prolog

I wrote a COM client in Prolog, adding convenient wrappers to call the C# functions. Here is my code:

Prolog Client Code

Prolog Client Code

The “open_com” predicate tries to connect to the COM object by passing its GUID or ProgID. When successful, it asserts a “fact” containing the object ID for subsequent use (removing any previously asserted IDs). Its counterpart “close_com” releases the COM object.

The “call_fn” predicate facilitates the actual call. It uses the “comclient_invoke_method_fun” to invoke the C# function through the object handle and gets the corresponding result.

If you look at the “add”, “mult”, “concat”, and “procid” predicates, you will notice that the names are in lowercase, even though the actual methods being called in C# are “add”, “Mult”, “Concat”, and “ProcID”. In Prolog, when you start a name in uppercase, it refers to a variable and not to the actual literal with that name. So we are forced to reference the C# functions in lowercase in Prolog, even though the actual function names might start in uppercase in C# (and that is the convention). It appears that the C# method names are lowercased by the “comclient” library in order to find the right match. I feel the library could have handled this differently, but it is not a big issue.

OK. Now let us look at the actual session in the Sicstus Prolog IDE.

Prolog Session

Prolog Session

You will notice that the Proc IDs from COM object as well as from the Prolog engine are the same. This confirms that the C# code runs as part of the Prolog process.

Everything works as expected. I am happy that COM solved my problem of connecting to C# from Prolog. 

You can download the C# code and Prolog code from here.

Have a nice weekend!

Tags: , , ,

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published.

Top