fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC: Expose X# run-time functions to C#

Expose X# run-time functions to C# 1 week 1 day ago #11116

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
I am opening a dbf using the DBFCDX driver, but it fails to open CDX file since it contains functions such as DTos().

How to add the entire set of the X# run-time function in C# and also create my BYO functions so that CDX can link to them successfully.

I created a C# function:
public string DToS(XSharp.__Date dDate)
        {
            return Dbf.DToS(dDate);
            
        }	

but I call Dbf.DbUseArea(...), I get $exception {"Specified cast is not valid."} XSharp.Error

Note: the DBF file opens using the DBFNTX driver.

Please advise.

Thanks!
Jamal

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Expose X# run-time functions to C# 1 week 1 day ago #11117

  Wolfgang Riedmann's Avatar Wolfgang Riedmann Away Posts: 1799
Hi Jamal,
you need to build your own intermediate DLL that uses the X# runtime and exposes only strongly typed methods.
I'm doing something like that to use DBFs in my X# Core applications (that don't use the X# runtime itself).
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy

www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 1 day ago #11118

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
Hi Jamal,

Did you add references to the XSharp runtime dlls? If you did, then the macro compiler should find them automatically.

I just tried the following and it seems to work fine, I get the first logical record printed:

public class Program
{
	static void Main()
	{
		string cPath;
		cPath = "c:\\...\\testcs.dbf";
		XSharp.RT.Functions.VoDbUseArea(true, "DBFCDX" , cPath , "alias" , true , false);
		XSharp.RT.Functions.DbGoTop();
		System.Console.WriteLine(XSharp.RT.Functions.FieldGet(1).ToString());
		XSharp.RT.Functions.VoDbCloseArea();		
	}
}
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 1 day ago #11119

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
Also, when you want to use in the dbf indexes (or in the macro compiler in gnerl) methods defined in your c# module, you need to put them in a class and add this assembly wide attribute:

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

Wolfgang, what you say is correct for directly calling X# runtime functions that have CLIPPER calling convention from c#, but when using the macrocompiler (so also functions in expressions) this is not a problem, because the macro compiler know how to call them.
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 1 day ago #11120

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
Hi Chris,

I am still getting the "Specified cast is not valid." error when calling XSharp.RT.Functions.DbUseArea().

Could you please test the attached dbf file and cdx?

Note: the CDX has one order on DToS(HIREDDATE). In X# the DBF file opens fine.

Jamal
Attachments:

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Expose X# run-time functions to C# 1 week 1 day ago #11121

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
It seems adding the following line:

XSharp.CoreDb.RddInfo(_SET_AUTOORDER, 1);

was causing the error. After I commented it out, the file opened fine!

I tested also in X#, and got the same error:
PRIVATE METHOD OpenDBFButton_Click(sender AS OBJECT, e AS System.EventArgs) AS VOID STRICT
             RddInfo(_SET_AUTOOPEN, true)
           
            RddInfo(_SET_AUTOORDER, 1)   // causes Specified cast is not valid. This works in VO.
            
            if (DbUseArea(true, "DBFCDX", "C:\TestingDir\TESTDBF.dbf", "TESTDBF", true, false))
                MessageBox.Show(LastRec().ToString())
                DBCloseArea()
                MessageBox.Show("Opened")
                
            else
                MessageBox.Show("Failed") 
            endif
            RETURN

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

Expose X# run-time functions to C# 1 week 1 day ago #11122

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
Thanks Jamal, problem confirmed and logged!
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 1 day ago #11123

  Wolfgang Riedmann's Avatar Wolfgang Riedmann Away Posts: 1799
Hi Chris,

Wolfgang, what you say is correct for directly calling X# runtime functions that have CLIPPER calling convention from c#, but when using the macrocompiler (so also functions in expressions) this is not a problem, because the macro compiler know how to call them.


I have a few classes in my XbaseInterface DLL:
- an AppDBServer class that inherits from the DBServer class
- a CoreDBFServer class that acts as proxy for the AppDBServer class and exposes methods like FieldGetString(), FieldGetLogic(), FieldGetDecimal() and a few more so I don't need to cast the return values in my Core dialec applications
- a XbDate class that works like a Nullable<DateTime>, but maintains only the date part. It is like the Xbase date, but usable without problems in Core dialect applications.

If there is some interest, I can share that library toghether with a sample.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy

www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 1 day ago #11124

  Juraj Halás's Avatar Juraj Halás Away Posts: 115
Hi Wolfgang,


I create the new app only as WPF in Core dialect. Sometimes I need to load an older DBF file. Your library would help.

Juraj

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 23 hours ago #11128

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
Hi Wolfgang,

That would be awesome!

Jamal

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 18 hours ago #11130

  Wolfgang Riedmann's Avatar Wolfgang Riedmann Away Posts: 1799
Hi Juraj, hi Jamal,
will prepare it tomorrow morning.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy

www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 15 hours ago #11131

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
Hi Chris,

I created an X# code file with something like the following. Named DLL as MyXSharpClassLibrary.
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

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 13 hours ago #11132

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
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.
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 1 week 7 hours ago #11133

  Wolfgang Riedmann's Avatar Wolfgang Riedmann Away Posts: 1799
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:
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

www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 6 days 14 hours ago #11138

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
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.
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.
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:\test\mynewtest"

    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.
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:\test\mynewtest.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




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:

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 6 days 11 hours ago #11141

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
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.
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 6 days 11 hours ago #11142

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
Hi Chris,

Wow! That worked great!!

Thanks!
Jamal

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 6 days 10 hours ago #11143

  Jamal's Avatar Topic Author Jamal Offline Posts: 148
Hi Chris,

In the mean time I found another way to load the assembly without creating a dummy function. I only had to call:
System.Reflection.Assembly.Load("MyXSharpClassLibrary");

Oh man! I could have saved hours by knowing this.

Thanks!
Jamal

Please Log in or Create an account to join the conversation.

Expose X# run-time functions to C# 6 days 9 hours ago #11144

  Chris Pyrgas's Avatar Chris Pyrgas Offline Posts: 1410
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:

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 :)
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

  • Page:
  • 1