[m-rev.] for post-commit review: add a standalone C# example

Julien Fischer jfischer at opturion.com
Sat Jan 15 03:27:37 AEDT 2022


Add a standalone C# example.

samples/csharp_interface/standalone_csharp/CSharpMain.cs:
samples/csharp_interface/standalone_csharp/Makefile:
samples/csharp_interface/standalone_csharp/mercury_lib.m:
samples/csharp_interface/standalone_csharp/README.md:
      As above.

Julien.

diff --git a/samples/csharp_interface/standalone_csharp/CSharpMain.cs b/samples/csharp_interface/standalone_csharp/CSharpMain.cs
new file mode 100644
index 0000000..2410dd1
--- /dev/null
+++ b/samples/csharp_interface/standalone_csharp/CSharpMain.cs
@@ -0,0 +1,52 @@
+// vim: ts=4 sw=4 et
+
+// All Mercury generated C# code lives in the mercury namespace.
+using mercury;
+using System;
+
+class CSharpMain {
+
+    static void Main(string[] args)
+    {
+        // Initialise the C# version of Mercury's standard library.
+        Console.WriteLine("CSharpMain: initialising Mercury standard library");
+        library.ML_std_library_init();
+
+        Console.WriteLine("CSharpMain: start main");
+        runProgram(args);
+        Console.WriteLine("CSharpMain: end main");
+
+        // Once Main returns, any Mercury finalisers will be run.
+    }
+
+    private static void runProgram(string[] args)
+    {
+        // The mercury_lib class contains a static method corresponding to each
+        // predicate or function that is foreign exported to C#.
+
+        // Call a Mercury predicate that does some I/O.
+        mercury_lib.WriteHello();
+
+        // Call a Mercury function.
+        Console.WriteLine("3^3 = " + mercury_lib.Cube(3));
+
+        // Call a semidet Mercury predicate. This also illustrates the
+        // use of a foreign exported enumeration in C#.
+        Console.WriteLine("IsCitrus(LEMON) is " +
+            (mercury_lib.IsCitrus(mercury_lib.LEMON) ? "true" : "false")); 
+        Console.WriteLine("IsCitrus(APPLE) is " +
+            (mercury_lib.IsCitrus(mercury_lib.APPLE) ? "true" : "false")); 
+
+        // Build up Mercury list of ints in C# 
+        // (See the section ``C# data passing conventions'' in the reference
+        // manual for details.)
+        list.List_1 mList = list.empty_list(); 
+        mList = list.cons(1, mList);
+        mList = list.cons(2, mList);
+        mList = list.cons(3, mList);
+ 
+        // At this point, mList is the Mercury list [3, 2, 1].
+        // Pass it as argument to a Mercury predicate. 
+        mercury_lib.PrintList(mList);
+    }
+}
diff --git a/samples/csharp_interface/standalone_csharp/Makefile b/samples/csharp_interface/standalone_csharp/Makefile
new file mode 100644
index 0000000..cab8b43
--- /dev/null
+++ b/samples/csharp_interface/standalone_csharp/Makefile
@@ -0,0 +1,39 @@
+#-----------------------------------------------------------------------------#
+# vim: ts=8 sw=8 noexpandtab
+#-----------------------------------------------------------------------------#
+# This source file is hereby placed in the public domain.
+#-----------------------------------------------------------------------------#
+
+MMC = mmc
+CSC = mcs 
+CLI = mono
+
+# We need to tell C# and CLI where to find about the Mercury standard
+# library.
+GRADE = csharp
+MER_LIB_DIR = $(dir $(shell which mmc))../lib/mercury/lib/$(GRADE)
+
+.PHONY: all
+all: run
+
+CSharpMain.exe: CSharpMain.cs mercury_lib.dll
+	$(CSC) -lib:$(MER_LIB_DIR),. -r:mercury_lib.dll -r:mer_std.dll CSharpMain.cs
+
+mercury_lib.dll: mercury_lib.m
+	$(MMC) --grade $(GRADE) --make libmercury_lib
+
+# The Microsoft .NET implementation does not have an equivalent of
+# MONO_PATH; you will need to copy mer_std.dll into this directory
+# in order to run the example.
+.PHONY: run
+run: CSharpMain.exe
+	MONO_PATH=$(MER_LIB_DIR) $(CLI) CSharpMain.exe
+
+.PHONY: clean
+clean:
+	$(MMC) --make mercury_lib.realclean
+	$(RM) mercury_lib.dll CSharpMain.exe
+	$(RM) -r Mercury
+
+.PHONY: realclean
+realclean: clean
diff --git a/samples/csharp_interface/standalone_csharp/README.md b/samples/csharp_interface/standalone_csharp/README.md
new file mode 100644
index 0000000..970312b
--- /dev/null
+++ b/samples/csharp_interface/standalone_csharp/README.md
@@ -0,0 +1,7 @@
+Standalone C# Example
+=====================
+
+This directory contains an example of how to call Mercury code from a C#
+program. The file [CSharpMain.cs](CSharpMain.cs) contains a small program
+written in C#.  This program calls the Mercury procedures exported by the
+Mercury library contained in the file [mercury_lib.m](mercury_lib).
diff --git a/samples/csharp_interface/standalone_csharp/mercury_lib.m b/samples/csharp_interface/standalone_csharp/mercury_lib.m
new file mode 100644
index 0000000..c335165
--- /dev/null
+++ b/samples/csharp_interface/standalone_csharp/mercury_lib.m
@@ -0,0 +1,101 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+
+:- module mercury_lib.
+:- interface.
+
+:- import_module io.
+:- import_module list.
+
+%-----------------------------------------------------------------------------%
+
+    % Write "Hello World" to the current Mercury text output stream.
+    %
+:- pred write_hello(io::di, io::uo) is det.
+
+    % cube(X) returns X * X * X.
+    %
+:- func cube(int) = int.
+
+    % Write the given list of ints to the current Mercury text output stream.
+    %
+:- pred print_list(list(int)::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- type fruit
+    --->    apple
+    ;       orange
+    ;       lemon.
+
+    % Succeeds if the given fruit is a citrus fruit.
+    %
+:- pred is_citrus(fruit::in) is semidet.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+    % Make the data constructors of the fruit/0 type visible to C#.
+    %
+:- pragma foreign_export_enum("C#", fruit/0, [uppercase]).
+
+:- pragma foreign_export("C#", is_citrus(in), "IsCitrus").
+
+is_citrus(orange).
+is_citrus(lemon).
+
+%-----------------------------------------------------------------------------%
+
+:- pragma foreign_export("C#", write_hello(di, uo), "WriteHello").
+
+write_hello(!IO) :-
+    io.print_line("Hello World", !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pragma foreign_export("C#", cube(in) = out, "Cube").
+
+cube(X) = X * X * X.
+
+%-----------------------------------------------------------------------------%
+
+:- pragma foreign_export("C#", print_list(in, di, uo), "PrintList").
+
+print_list(List, !IO) :-
+    io.print_line(List, !IO).
+
+%-----------------------------------------------------------------------------%
+%
+% Initialiser for this library.
+%
+
+:- initialise initialiser/2.
+
+:- pred initialiser(io::di, io::uo) is det.
+
+initialiser(!IO) :-
+    io.print_line("mercury_lib: the initialiser has now been invoked.", !IO).
+
+%-----------------------------------------------------------------------------%
+%
+% Finaliser for this library.
+%
+
+:- finalise finaliser/2.
+
+:- pred finaliser(io::di, io::uo) is det.
+
+finaliser(!IO) :-
+    io.print_line("mercury_lib: the finaliser has now been invoked.", !IO).
+
+%-----------------------------------------------------------------------------%
+:- end_module mercury_lib.
+%-----------------------------------------------------------------------------%


More information about the reviews mailing list