ReloadPublicShow sourceeditswicli.pl -- SWI-Prolog 2-Way interface to .NET/Mono

Introduction

This is an overview of an interface which allows SWI-Prolog programs to dynamically create and manipulate .NET objects.

Here are some significant features of the interface and its implementation:

author
- Douglas Miles
Edit predicatecli_load_lib(+AppDomainName, +AssemblyPartialName, +FullClassName, +StaticMethodName)
Loads an assembly into AppDomainName

cli_load_lib/4 is what was used to bootstrap SWICLI (it defined the next stage where cli_load_assembly/1) became present

remember to: export LD_LIBRARY_PATH=/development/opensim4opencog/bin:$LD_LIBRARY_PATH

in swicli.pl we called:

:- cli_load_lib('SWIProlog','Swicli.Library','Swicli.Library.Embedded','install').
Edit predicatecli_lib_type(-LibTypeName)
LibTypeName is an atom that denotes the implementation class SWICLI uses
Edit predicatecli_load_assembly(+AssemblyPartialNameOrPath)
Edit predicatecli_load_assembly_uncaught(+AssemblyPartialNameOrPath)
the cli_<Predicates> came because we had:
?- cli_load_assembly('Swicli.Library').

The uncaught version allows exception to come from .NET

Edit predicatecli_load_assembly_methods(+AssemblyPartialNameOrPath, +OnlyPrologVisible, +StringPrefixOrNull)
Loads foriegn predicates from Assembly
?- cli_load_assembly_methods('Swicli.Library', @false, "cli_").
Edit predicatecli_add_assembly_search_path(+Path)
Edit predicatecli_remove_assembly_search_path(+Path)
Add or remove directories to the search path
?- cli_add_assembly_search_path('c:/myproj/bin').

?- cli_remove_assembly_search_path('c:/myproj/bin').

This now makes the System assembly resolver see Assemblies in that directory

Simular to Windows: adding to %PATH% Linux: adding to $MONO_PATH

Edit predicatecli_non_obj(+Obj)
is null or void or var
Edit predicatecli_non_null(+Obj)
is not null or void
Edit predicatecli_is_null(+Obj)
equiv to Obj == @(null)
Edit predicatecli_null(+Obj)
construct a null
Edit predicatecli_is_true(+Obj)
equiv to Obj == @(true)
Edit predicatecli_true(+Obj)
construct a @(true)
Edit predicatecli_is_false(+Obj)
equiv to Obj == @(false)
Edit predicatecli_false(+Obj)
construct a @(false)
Edit predicatecli_is_void(+Obj)
equiv to Obj == @(void)
Edit predicatecli_void(+Obj)
construct a @(void)
Edit predicatecli_is_type(+Obj)
equiv to cli_is_type(Obj,'System.Type')
Edit predicatecli_is_object(+Obj)
is Object a CLR object and not null or void (includes struct,enum,object,event)
Edit predicatecli_is_tagged_object(+Obj)
is Object a ref object (maybe null or void) (excludes struct,enum,object/N,event refernces)
Edit predicatecli_is_ref(+Obj)
is Object a ref object and not null or void (excludes struct,enum,object/N,event refernces)
Edit predicatecli_memb(O, F, X)
Object to the member infos of it
Edit predicatecli_is_type(+Impl, ?Type)
tests to see if the Impl Object is assignable to Type
Edit predicatecli_subclass(+Subclass, +Superclass)
tests to see if the Subclass is assignable to Superclass
Edit predicatecli_typespec(+ClazzSpec, -Value)
coerces a ClazzSpec to a Value representing a TypeSpec term
Edit predicatecli_add_tag(+RefObj, +TagString)
lowlevel access to create a tag name
Edit predicatecli_remove_tag(+TagString)
lowlevel access to remove a tag name
Edit predicatecli_to_ref(+Obj, +Ref)
return a @(Ref) version of the object (even if a enum)
15 ?- cli_to_ref(sbyte(127),O),cli_get_type(O,T),cli_writeln(O is T).
"127"is"System.SByte"
O = @'C#283319280',
T = @'C#283324332'.

16 ?- cli_to_ref(long(127),O),cli_get_type(O,T),cli_writeln(O is T).
"127"is"System.Int64"
O = @'C#283345876',
T = @'C#283345868'.

17 ?- cli_to_ref(ulong(127),O),cli_get_type(O,T),cli_writeln(O is T).
"127"is"System.UInt64"
O = @'C#283346772',
T = @'C#283346760'.

15 ?- cli_to_ref(sbyte(127),O),cli_get_type(O,T),cli_writeln(O is T).
"127"is"System.SByte"
O = @'C#283319280',
T = @'C#283324332'.

16 ?- cli_to_ref(long(127),O),cli_get_type(O,T),cli_writeln(O is T).
"127"is"System.Int64"
O = @'C#283345876',
T = @'C#283345868'.

18 ?- cli_to_ref(343434127,O),cli_get_type(O,T),cli_writeln(O is T).
"343434127"is"System.Int32"
O = @'C#281925284',
T = @'C#281925280'.

19 ?- cli_to_ref(3434341271,O),cli_get_type(O,T),cli_writeln(O is T).
"3434341271"is"System.UInt64"
O = @'C#281926616',
T = @'C#283346760'.

21 ?- cli_to_ref(343434127111,O),cli_get_type(O,T),cli_writeln(O is T).
"343434127111"is"System.UInt64"
O = @'C#281930092',
T = @'C#283346760'.

28 ?- cli_to_ref(34343412711111111111111111111111111111,O),cli_get_type(O,T),cli_writeln(O is T).
"34343412711111111111111111111111111111"is"java.math.BigInteger"
O = @'C#281813796',
T = @'C#281810860'.
Edit predicatecli_to_immediate(+Ref, -Immediate)
return an Immediate value of Ref to just REf if no immediate type exists
Edit predicatecli_cast(+Value, +ClazzSpec, -Ref)
Edit predicatecli_cast_immediate(+Value, +ClazzSpec, -Immediate)
Convert the type of Value to ClazzSpec returning eigther a Ref or Immediate value.
?- cli_cast(1,'double',X).
X = @'C#568261440'.

?- cli_cast(1,'System.DayOfWeek',X).
X = @'C#568269000'.

?- cli_cast_immediate(1,'System.DayOfWeek',X).
X = enum('DayOfWeek', 'Monday').

?- cli_cast_immediate(1.0,'System.DayOfWeek',X).
X = enum('DayOfWeek', 'Monday').

?- cli_cast_immediate(1.01,'System.DayOfWeek',X).
ERROR: Having time of it convcerting 1.01 to System.DayOfWeek why System.ArgumentException: Requested value '1.01' was not found.
Edit predicatecli_tracker_begin(-Tracker)
Return a Tracker ref and all objects created from this point can be released via cli_tracker_free/1
Edit predicatecli_tracker_free(+Tracker)
See also
- cli_tracker_begin/1
Edit predicatecli_free(+RefObject)
remove a RefObject from the heap
Edit predicatecli_heap(+RefObject)
Pin a RefObject onto the heap
Edit predicatecli_with_gc(+Call)
as ref objects are created they are tracked .. when the call is complete any new object tags are released uses Forienly defined cli_tracker_begin/1 and cli_tracker_free/1
Edit predicatecli_with_lock(+Lock, +Call)
Lock the first arg while calling Call
Edit predicatecli_lock_enter(+LockObj)
Does a Monitor.Enter on LockObj
Edit predicatecli_lock_exit(+LockObj)
Does a Monitor.Exit on LockObj
Edit predicatecli_write(+Obj)
writes an object out
Edit predicatecli_writeln(+Obj)
writes an object out with a new line
Edit predicateto_string(+Obj, -String)
Edit predicatecli_to_str(+Obj, -String)
Resolves inner @(Obj)s to strings
Edit predicatecli_to_str_raw(+Obj, -String)
Edit predicatecli_java_to_string(+Obj, -Value)
Resolves @(Obj) to string
Edit predicatecli_halt
Edit predicatecli_halt(+Obj)
Edit predicatecli_throw(+Ex)
throw an exception to .NET
Edit predicatecli_break(+Ex)
Edit predicatecli_col(+Col, -Elem)
Edit predicatecli_enumerator_element(+Enumer, -Elem)
Edit predicatecli_iterator_element(+Iter, -Elem)
Iterates out Elem for Col/Iter/Enumer
   ?- cli_new('System.Collections.Generic.List'('System.String'),[int],[10],Obj).
   Obj = @'C#516939544'.


   ?- cli_get($Obj,'Count',Out).
   Out = 0.


   ?- cli_call($Obj,'Add'("foo"),Out).
   Out = @void.


   ?- cli_call($Obj,'Add'("bar"),Out).
   Out = @void.


   ?- cli_get($Out,'Count',Out).
   Out = 2.


   ?- cli_col($Obj,E).
   E = "foo" ;
   E = "bar" ;
   false.
Edit predicatecli_col_add(+Col, +Item)
add an Item to Col
Edit predicatecli_col_contains(+Col, +Item)
Test an Item in Col
Edit predicatecli_col_remove(+Col, +Item)
Remove an Item in Col
Edit predicatecli_col_removeall(+Col)
Clears a Col
Edit predicatecli_col_size(+Col, ?Count)
Returns the Count
Edit predicatecli_new_prolog_collection(+PredImpl, +ElementType, -PBD)
Edit predicatecli_make_list(+Obj, +Arg2, +Arg3)
See also
- cli_new_list_1/2
Edit predicatecli_new_list_1(+Obj, +Arg2, +Arg3)
See also
- cli_make_list/2
Edit predicatecli_sublist(+Mask, +List)
Test to see if Mask appears in List
Edit predicatecli_array_to_list(+Obj, +Arg2)
Edit predicatecli_array_to_term(+ArrayValue, -Value)
Edit predicatecli_array_to_termlist(+ArrayValue, -Value)
Edit predicatecli_term_to_array(+ArrayValue, -Value)
Edit predicatecli_array_to_term_args(+Array, -Term)
todo
Edit predicatecli_map(Map, ?Key, ?Value)
Edit predicatecli_map_add(+Map, +Key, +Value)
Edit predicatecli_map_set(+Map, +Key, +Value)
Edit predicatecli_map_remove(+Map, +Key)
Edit predicatecli_map_remove(+Map, ?Key, ?Value)
Edit predicatecli_map_removeall(+Map)
Edit predicatecli_map_size(+Map, -Count)
Map calls
Edit predicatecli_preserve(TF, :Call)
make Call with PreserveObjectType set to TF
Edit predicatemember_elipse(Ele, Elipse)
?- member_elipse(E,{a,b,c}).
E = a ;
E = b ;
E = c.
Edit predicatecli_to_data(+Ref, -Term)
converts a Ref to prolog Term
?- cli_cast("Yellow",'System.Drawing.Color',C),cli_to_data(C,D),writeq(D).
["R"=255,"G"=255,"B"=0,"A"=255,"IsKnownColor"= @true,"IsEmpty"= @false,"IsNamedColor"= @true,"IsSystemColor"= @false,"Name"="Yellow"]
C = @'C#802963000',
D = ["R"=255, "G"=255, "B"=0, "A"=255, "IsKnownColor"= @true, "IsEmpty"= @false, "IsNamedColor"= @true, "IsSystemColor"= @ ..., ... = ...].
Edit predicatecli_unify(OE, PE)
Edit predicatecli_new(+ClassNameWithParams, -Result)
Edit predicatecli_new(+ClazzSpec, +Params, -Result)
Edit predicatecli_new(+ClazzSpec, +MemberSpec, +Params, -Result)
?- cli_load_assembly('IKVM.OpenJDK.Core')
?- cli_new('java.lang.Long'(long),[44],Out),cli_to_str(Out,Str).

same as..

?- cli_new('java.lang.Long',[long],[44],Out),cli_to_str(Out,Str).

arity 4 exists to specify generic types

?- cli_new('System.Int64',[int],[44],Out),cli_to_str(Out,Str).
?- cli_new('System.Text.StringBuilder',[string],["hi there"],Out),cli_to_str(Out,Str).
?- cli_new('System.Int32'(int),[44],Out),cli_to_str(Out,Str).

ClazzSpec can be:

if ClazzSpec is an object (non-array) type or descriptor and Params is a list of values or references, then Result is the result of an invocation of that type's most specifically-typed constructor to whose respective formal parameters the actual Params are assignable (and assigned)

if ClazzSpec is an array type or descriptor and Params is a list of values or references, each of which is (independently) assignable to the array element type, then Result is a new array of as many elements as Params has members, initialised with the respective members of Params;

if ClazzSpec is an array type or descriptor and Params is a non-negative integer N, then Result is a new array of that type, with N elements, each initialised to CLR's appropriate default value for the type;

If Result is {Term} then we attempt to convert a new PlTerm instance to a corresponding term; this is of little obvious use here, but is consistent with cli_call/4 and cli_get/3

Make a "new string[32]" and get it's length.

 ?- cli_new(array(string),[int],[32],O),cli_get(O,'Length',L).
Edit predicatecli_call(+ClazzOrInstance, +CallTerm, -Result)
Edit predicatecli_call(+ClazzOrInstance, +MethodSpec, +Params, -Result)
Edit predicatecli_call_raw(+ClazzOrInstance, +MethodSpec, +Params, -Result)
Edit predicatecli_raise_event_handler(+ClazzOrInstance, +MemberSpec, +Params, -Result)
ClazzOrInstance should be:

MethodSpec should be:

Params should be:

CallTerm should be:

finally, an attempt will be made to unify Result with the returned result

Edit predicatecli_lib_call(+CallTerm, -Result)
CallTerm should be:

finally, an attempt will be made to unify Result with the returned result

Edit predicatecli_set(+Obj, +NameValueParis:list)
Edit predicatecli_get(+Obj, +NameValueParis:list)
gets or set multiple values
Edit predicatecli_get(+ClazzOrInstance, +MemberSpec, -Value)
Edit predicatecli_set(+ClazzOrInstance, +MemberSpec, +Value)
Edit predicatecli_get_raw(+ClazzOrInstance, +MemberSpec, -Value)
Edit predicatecli_set_raw(+ClazzOrInstance, +MemberSpec, +Value)
Edit predicatecli_set_property(+ClazzOrInstance, +MemberSpec, +IndexValues, +Value)
Edit predicatecli_get_property(+ClazzOrInstance, +MemberSpec, +IndexValues, -Value)
ClazzOrInstance can be:

MemberSpec can be:

IndexValues can be:

Value:

Edit predicatecli_new_event_waiter(+ClazzOrInstance, +MemberSpec, -WaitOn)
Creates a new ManualResetEvent (WaitOn) that when an Event is called WaitOn in pulsed so that cli_block_until_event/3 will unblock
Edit predicatecli_add_event_waiter(+WaitOn, +ClazzOrInstance, +MemberSpec, -NewWaitOn)
Adds a new Event to the ManualResetEvent (WaitOn) created by cli_new_event_waiter/3
Edit predicatecli_block_until_event(+WaitOn, +Time, +Lambda)
Calls (foriegnly defined) cli_block_until_event/4 and then cleansup the .NET objects.
Edit predicatecli_block_until_event(+WaitOn, +MaxTime, +TestVarsCode, -ExitCode)
foriegnly defined tododocs
Edit predicatecli_add_event_handler(+Term1, +Arity, +IntPtrControl, Pred)
See also
- cli_add_event_handler/4
Edit predicatecli_add_event_handler(+ClazzOrInstance, +MemberSpec, +PrologPred)
Create a .NET Delegate that calls PrologPred when MemberSpec is called
Edit predicatecli_remove_event_handler(+ClazzOrInstance, +MemberSpec, +PrologPred)
Edit predicatecli_hide(+Pred)
hide Pred from tracing
Edit predicatecli_notrace(+Call) is nondet
use call/1 with trace turned off
Edit predicatecli_class_from_type(+Value, -Value)
Edit predicatecli_find_class(+ClazzName, -ClazzObject)
Edit predicatecli_find_type(+ClazzSpec, +ClassRef)
Edit predicatecli_get_class(+Value, -Value)
Edit predicatecli_get_classname(+Value, -Value)
Edit predicatecli_get_type(+Value, -Value)
Edit predicatecli_get_type_fullname(+Value, -Value)
Edit predicatecli_type_from_class(+Value, -Value)
todo
Edit predicatecli_new_delegate_term(+TypeFi, +PrologPred, +BooleanSaveKey, -Delegate)
Edit predicatecli_getterm(+ValueCol, +Value, -Value)
Edit predicatecli_new_array(+ClazzSpec, +Rank, -Value)
Edit predicatecli_new_delegate(+DelegateClass, +PrologPred, -Value)
todo
Edit predicatecli_is_layout(+MemberSpec)
Edit predicatecli_add_layout(+ClazzSpec, +MemberSpec)
Edit predicatecli_add_layout(+ClazzSpec, +MemberSpec, +ToSpec)
Edit predicatecli_add_recomposer(+ClazzSpec, +MemberSpec, +Obj2r, +R2obj)
need doc!
Edit predicatecli_find_constructor(+ClazzSpec, +MemberSpec, -Method)
Edit predicatecli_find_method(+ClazzOrInstance, +MemberSpec, -Method)
Edit predicatecli_member_doc(+Memb, +Doc, +Xml)
Edit predicatecli_members(+ClazzOrInstance, -Members)
Edit predicatecli_add_shorttype(+Short, +Long)
Edit predicatecli_props_for_type(+ClazzSpec, +MemberSpecs)
need doc
Edit predicatecli_new_array(Arg1, Arg2, Arg3)
Edit predicatecli_array_fill(Arg1, Arg2)
Edit predicatecli_array_fill_values(Arg1, Arg2)
need docs
Edit predicatecli_special_unify(Arg1, Arg2)
Edit predicatecli_fmt(Arg1, Arg2, Arg3)
Edit predicatecli_intern(Arg1, Arg2, Arg3)
Edit predicatecli_memb(Arg1, Arg2)
Edit predicatecli_to_data(Arg1, Arg2, Arg3)
Edit predicatecli_new_prolog_dictionary(Arg1, Arg2, Arg3, Arg4)
Edit predicatecli_set_element(Arg1, Arg2, Arg3)
Edit predicatecli_add_foreign_methods(Arg1, Arg2, Arg3)
Edit predicatecli_array_to_length(Arg1, Arg2)
Edit predicatecli_get_symbol(Arg1, Arg2, Arg3)
Edit predicatecli_add_element(Arg1, Arg2)
Edit predicatecli_debug(Arg1)
Edit predicatecli_expanded(Arg1, Arg2)
Edit predicatemodule_functor(Arg1, Arg2, Arg3, Arg4)
Edit predicatecli_link_swiplcs(Arg1)
Edit predicatecli_make_default(Arg1, Arg2)
Edit predicatecli_subproperty(Arg1, Arg2)
Edit predicatecli_demo(Arg1, Arg2)
Edit predicatecli_expand(Arg1, Arg2)
Edit predicatecli_set_hook(Arg1, Arg2, Arg3)
Edit predicatecli_get_hook(Arg1, Arg2, Arg3)
Edit predicatecli_fmt(Arg1, Arg2)
Edit predicatecli_is_defined(Arg1, Arg2)
Edit predicatecli_eval(Arg1, Arg2, Arg3)
Edit predicatecli_eval_hook(Arg1, Arg2, Arg3)
Edit predicatecli_interned(Arg1, Arg2, Arg3)
need docs!
Edit predicatecli_test_array_to_term1(-Value)
Edit predicatecli_test_array_to_term2(-Value)
Edit predicatecli_test_opt(+Incoming, ?REFInt32Outbound)
Edit predicatecli_test_opt(+Incoming, +StringOptionalstr, ?REFInt32Outbound)
Edit predicatecli_test_out(+Incoming, ?REFInt32Outbound)
Edit predicatecli_test_pbc(+Pred, +Counted)
Edit predicatecli_test_pbct(+Pred, +Counted)
Edit predicatecli_test_pbd(+Pred, +Counted)
Edit predicatecli_test_pbdt(+Pred, +Counted)
Edit predicatecli_test_ref(+Incoming, ?REFInt32Outbound)
Edit predicatecli_test_ref(+Incoming, ?REFStringOptionalstr, ?REFInt32Outbound)
Edit predicatecli_test_var_arg(?REFInt32Outbound, +ArrayOfInt32Incoming)
Assembly definition test preds for Examples