Expose X# run-time functions to C#

This forum is meant for questions and discussions about the X# language and tools
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Expose X# run-time functions to C#

Post by wriedmann »

Hi Juraj, hi Jamal,
will prepare it tomorrow morning.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Jamal
Posts: 315
Joined: Mon Jul 03, 2017 7:02 pm

Expose X# run-time functions to C#

Post by Jamal »

Hi Chris,

I created an X# code file with something like the following. Named DLL as MyXSharpClassLibrary.

Code: Select all

USING System
USING System.Collections.Generic
USING System.Text


FUNCTION TestFunction() AS STRING         
      
      RETURN "Test"
When opening the a DBF in X# where the CDX key expression contains the above, the DBF opens fine and I also the function is accessible in regular code.

Now in C# I tried adding the attribute to the C# project

[assembly: XSharp.Internal.ClassLibrary("MyXSharpClassLibrary", "")]
namespace Test
{
// code ...
}

But this causes the following compile time error.

causes Severity Code Description Project File Line Suppression State
Error CS0579 Duplicate 'XSharp.Internal.ClassLibrary' attribute


[assembly: XSharp.Internal.ClassLibrary("MyRuntimeFuncsClass", "")]

Any clue what might be wrong?

Thanks!
Jamal
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Expose X# run-time functions to C#

Post by Chris »

Hi Jamal,

Maybe indeed you accidentally defined this attribute twice?

Also you need to specify the class name (complete, including the namespace) in the first parameter, not the assembly name of the library, but that has to do with the runtime behavior only of course.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Expose X# run-time functions to C#

Post by wriedmann »

Hello,
I have now prepared the library (it differs from the one I'm using internally because I have removed some non-needed classes).
You can find it here:
https://riedmann.it/download/XbaseInterface.zip
I have included the binaries, the single source files and a XIDE export file.
The most interesting class may be the XbDate class as it shows how the define your own datatype including the support for operators.
All these classes are used in production, but of course will contain errors and be incomplete.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Jamal
Posts: 315
Joined: Mon Jul 03, 2017 7:02 pm

Expose X# run-time functions to C#

Post by Jamal »

Hi Chris,

Hopefully, you can spot why the macro compiler cannot see the custom X# function which is part the key expression when being a DBF is opened in C#. I attached test.zip which contains the projects and sample dbf and cdx.

I've created a X# DLL named: MyXSharpClassLibrary which has a Code File.

I declared a function KeyExp() which is used as part of an CDX Index expression, for example:
DbCreateOrder("FIRST", cDbf,"Upper(FIRST)+KeyExp()")

This is just a sample and it can be more complex and longer; It is easier to manage.

Code: Select all

USING System
USING System.Collections.Generic
USING System.Text
using System.Runtime.CompilerServices
using XSharp
using XSharp.Internal
using XSharp.RT

function KeyExp() as string
        return iif(_FIELD->FIRST > "R", "Y", "N")
Create test dbf with CDX orders in X#. I added a reference to the MyXSharpClassLibrary. No issues here.

Code: Select all

USING System    
USING System.Collections.Generic
USING System.Linq
USING System.Text
using System.Runtime.CompilerServices
using XSharp
using XSharp.Internal
using XSharp.RT
using MyXSharpClassLibrary


FUNCTION Start() AS VOID STRICT
   LOCAL cDbf AS STRING
	cDbf := "c:testmynewtest"

    RddInfo(_SET_AUTOOPEN, true)
    
	RddSetDefault("DBFCDX")
    
	DbCreate(cDbf , {{"LAST" , "C" , 10,0}, {"FIRST", "C", 10, 0}})
	
	DbUseArea(true, "DBFCDX", cDbf, "mynewtest", false, false)
    ? DbCreateOrder("FIRST", cDbf,"Upper(FIRST)+KeyExp()")
	? DbCreateOrder("LAST",  cDbf,"Upper(LAST)")
	
	LOCAL aValues, aValues2 AS ARRAY
	aValues := {"JACK", "MARK", "HARRY", "Mary", "ROB", "SALLY"}
    aValues2 := {"MAC", "JIM",  "paul",   "SUE",   "THERE", "ELF"}
    
	FOR LOCAL n := 1 AS DWORD UPTO ALen(aValues)
		DbAppend()
		FieldPut(1,aValues[n])
        FieldPut(2,aValues2[n])
	NEXT
    
    DbGoTop()
    WHILE !EOF()
         ? FieldGet(1), FieldGet(2)
         DbSkip(1)
    END
    ?
    ? "Set order: "
    ? DbSetOrder("FIRST")
    DbGoTop()
    WHILE !EOF()
         ? FieldGet(1), FieldGet(2)
         DbSkip(1)
    END
    ? "Records:", LastRec()
    
    ? DbSetOrder("LAST")
    DbGoTop()
   WHILE !EOF()
         ? FieldGet(1), FieldGet(2)
         DbSkip(1)
   END
	
	DbCloseArea()
    WAIT
	RETURN	
    
I created a C# app and added MyXSharpClassLibrary reference the the C# app. The app compiles fine.

Code: Select all

using System;
using System.Windows.Forms;
using XSharp;
using XSharp.RT;
using XSharp.VO;
using XSharp.RDD;
using XSharp.Internal;
using XSharp.Core;    

[assembly: XSharp.Internal.ClassLibrary("Functions", "MyXSharpClassLibrary")]   // is this correct ??
namespace DBFCDX_CS_Sample
{
    public partial class Form1 : Form
    {
        public const int RDD_INFO = 100;
        public const int _SET_AUTOOPEN = RDD_INFO + 4;
        public const int _SET_AUTOORDER = RDD_INFO + 5;
        public Form1()

        {
            InitializeComponent();
        }

        private void ReservationsDBFbutton_Click(object sender, EventArgs e)
        {

             XSharp.CoreDb.RddInfo(_SET_AUTOOPEN, true);

            if (XSharp.RT.Functions.DbUseArea(true, "DBFCDX", @"C:testmynewtest.dbf", "newtestdbf", true, false))
            {
                XSharp.RT.Functions.DbSetOrder("LAST");
               // MessageBox.Show(XSharp.RT.Functions.FCount().ToString());
                MessageBox.Show(XSharp.RT.Functions.LastRec().ToString());
                XSharp.RT.Functions.VoDbCloseArea();
            }                       
           
        }
               
    }
}

Please see the attached screenshot of error message with InnerException: Exception of type 'XSharp.RDD.RddError' was thrown. and SubCodeText: "Expression for macro compiler left"

Which indicates that the Macro Compiler cannot see the KeyExp() function and thus fails to open the DBF file.

What I am doing wrong
2019-10-11_15-27-42.png
2019-10-11_15-27-42.png (170.97 KiB) Viewed 493 times

Chris wrote:Hi Jamal,

Maybe indeed you accidentally defined this attribute twice?

Also you need to specify the class name (complete, including the namespace) in the first parameter, not the assembly name of the library, but that has to do with the runtime behavior only of course.
Attachments
test.zip
(1.69 MiB) Downloaded 68 times
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Expose X# run-time functions to C#

Post by Chris »

Hi Jamal,

I found the problem, it's just because the library has not been loaded yet, so the macro compiler cannot find the function in it. To ensure it is loaded, just add a call to any function of this library in your code, before opening the dbf. now it should work. (just ignore the return value of your function call).

About:

[assembly: XSharp.Internal.ClassLibrary("Functions", "MyXSharpClassLibrary")] // is this correct ??

No, this would be needed only if you wanted the macro compiler to see functions defined in your _c#_ library, in which case you would need to specify the name of the c# class that holds your functions (methods) in the first param (and keep the 2nd param empty). In the case of X# libraries, the macro compiler already knows where to search for functions, so you do not need this attribute.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Jamal
Posts: 315
Joined: Mon Jul 03, 2017 7:02 pm

Expose X# run-time functions to C#

Post by Jamal »

Hi Chris,

Wow! That worked great!!

Thanks!
Jamal
Jamal
Posts: 315
Joined: Mon Jul 03, 2017 7:02 pm

Expose X# run-time functions to C#

Post by Jamal »

Hi Chris,

In the mean time I found another way to load the assembly without creating a dummy function. I only had to call:

Code: Select all

System.Reflection.Assembly.Load("MyXSharpClassLibrary");
Oh man! I could have saved hours by knowing this.

Thanks!
Jamal
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Expose X# run-time functions to C#

Post by Chris »

Hi Jamal,
Jamal wrote:Hi Chris,

In the mean time I found another way to load the assembly without creating a dummy function. I only had to call:

Code: Select all

System.Reflection.Assembly.Load("MyXSharpClassLibrary");
Oh man! I could have saved hours by knowing this.

Thanks!
Jamal
You're welcome! First time I had this I also lost many hours! This time it took much less :)
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Post Reply