Easy to Create, Easy to Change - Easy to use!


Custom CDF and strings


Started by George Washington
Search
You will need to Sign In to be able to add or comment on the forum!

Custom CDF and strings

Hi there,

I read the blog entry on how to create custom cdf and I am really excited about that. It has been long time since I desired to add some function and cannot do that was kind of frustrating. Anyway, I followed the example and everything worked straight away. I created some simple functions by myself and those work well, unless there are string involved. I am trying to create a trim function and I have a working algorithm, the dll is built without errors, but when I try to use it in dataease it crashes. I am using c so I do not really use strings, but *char. Is there some specific issue I have to take in mind when creating functions dealing with strings?

Regards

Written by George Washington 09/06/15 at 14:57:16 Dataease [{8}]FIVE

Re:Custom CDF and strings

Hi George, and thanks for the interest in extending DfW your self using a custom CDF.

The most common reason for DfW to crash when returning a string from a CDF is simply that the memory used by the string it self is released before DfW can get to it. To fix this, simply make sure you allocate a buffer that stay in memory for as long as the DLL is loaded. The simplest way to achieve this is to create a global variable outside of your function, then use this buffer for your trimming and then return this buffer when returning string data to DfW.

//from examplecdf.h
EXAMPLECDF_API LPCSTR returnstring(void);

//from examplecdf.cpp
char _returnbuffer[256];

// This is an example of an exported function that returns a string buffer
EXAMPLECDF_API LPCSTR returnstring(void)
{
    strncpy_s(_returnbuffer, "42",256);
    return _returnbuffer;
}

CDFs are loaded the first time they are used and do not get reloaded or released before you shut down DfW and start i up again. So every time you make a change to your function and need to test a new version, make sure that you shut down DfW and start it again before you do a new test.

Hope this helps. We will come back with a more extensive  article on CDFs and some example code to test them later.

Written by DataEase Development 10/06/15 at 10:33:25 Dataease [{8}]FIVE

Re:Custom CDF and strings

Hi there,

I know this is a one year old thread, but I put this problem aside and now it has been brought again to my attention... any news on this issue (it seems that it is possible to build only functions returning a string)?

Regards

Written by George Washington 16/05/16 at 07:25:48 Dataease [{8}]FIVE

Re:Re:Custom CDF and strings

Pretty much on the same subject about creating CDF.

Windows o/s alone comes with 100s of functions. For us to use the Windows API, we need an add-on into DataEase. As soon as we can use that Add-on. We can open up Windows API and use 1000s of functions already available. There won't be a need for CDF :-)

I think previous DataEase developers did try something like this in a version. I think 7.0 or something, I can't even remember now.

Written by Jeyarajah Arulrajah 10/06/15 at 13:26:23 Dataease [{8}]FIVE

Re:Re:Custom CDF and strings

Thank you G3 development for the clarification. I am still missing something on CDF development, cause a lot of very simple routines give GPF in an apparently random way. I can't help to read more about that topic. I know the development team is really busy on the de 8.5 development, but if you could release just the source code of a working CDF with few  functions on it, it would be grate and I would really appreciate that.

Written by George Washington 11/06/15 at 13:16:44 Dataease [{8}]FIVE

Re:Re:Custom CDF and strings

Up, I really need this.

Written by George Washington 25/05/16 at 06:12:31 Dataease [{8}]FIVE

Re:Re:Re:Custom CDF and strings

Arul... Simplistic solutions aren't always the simplest solutions. ;-)

The CDF interface is very much an interface to the Windows API and everything else.

There is no way you can magically create a way to use the WIndows API that is any simpler than the CDF interface in DataEase.

DataEase itself is partly an simplified interfaced to Windows/Windows API development.

If we did what you want, the point of DataEase would have evaporated as you must then have the same programming knowledge/understanding as a C/C++ developer.

Using the Windows API is not as simple as calling a function in DataEase. There is a lot of rules, limitations and environment restrictions that has to be adhered to. I know how you had GPFs and I can promise you that you would get even more closely acquainted with them if you tried to call Windows API stuff directly from DataEase.

Our job is to develop a RAD environment with a "minimum" of complexity for the developer. 

With the CDF interface you can make any "add-on" functionality using any and all WIndows API functions and any other functionality or code you can run in Windows.

You can quickly develop the majority of the application and if there is things that you can't do in DataEase you can invest the time/money in a specialist/tailor made CDF to do the rest.

Written by DataEase 11/06/15 at 12:32:02 Dataease [{8}]FIVE

Re:Re:Re:Custom CDF and strings

When you refer to the previous Developers attempting to access the Windows API you are thinking of using ShellExecute to call some Shell functions in Windows. This is not strictly the same thing.

https://msdn.microsoft.com/en-us/library/windows/d....aspx

You can use ShellExecute to execute functions in other programs including Windows, but it is not very easy...

The sole purpose of a product like DataEase is to make something complex understandable, so it would be a big step in the wrong direction if we tried to go in the other direction.

Written by DataEase 11/06/15 at 12:45:27 Dataease [{8}]FIVE

Re:Re:Re:Custom CDF and strings

Hi, to call with parmeters as input is a bit more complicated than the first example in CDF part1. Here is part 2 that tells more of the story of creating CDFs. Added the code example as well for you all to play with.

Written by DataEase Development 14/06/15 at 10:21:47 Dataease [{8}]FIVE

Re:Re:Re:Custom CDF and strings

This is a developer interface for specially interested parties and not a priority when it comes to development/support.

It has not been updated for 20 years so using a new compiler etc, might in itself be the problem as your DLL might not be compatible with the interface.

DataEase convert automatically between string to number etc, so if String return value works and double doesn't then the solution is to return a string. 

Most DataEase functions return string anyway as it is the most practical return value as we can return error messages etc directly if the function fails.

We can't do anything about the API/Interface as it would interfere with the existing CDF libraries.

Written by DataEase 25/05/16 at 08:42:56 Dataease [{8}]FIVE

Re:Re:Re:Re:Custom CDF and strings

No. I am talking about different thing here.
Actually I managed to dig into old documents and found this.

In the following script, addressof is the new function introduced by the DE developer in the past.
Not sure which DE version. In the example below it will use the GetDefaultPrinterA Window API 

--------------------------

define "BufName" text 49 .

define "BufLen" text 4 .

define "prtName" number .

define "prtLen" number .

define "retval" number .

BufName := "1234567890123456789012345678901234567890123456789" .

Buflen := "1" . -- Ascii 49

prtName := addressof(BufName) .

prtLen := addressof(BufLen) .

retval := GetDefaultPrinterA( prtName, prtLen ) .

message BufName window .

-------------------------------

Written by Jeyarajah Arulrajah 11/06/15 at 13:14:36 Dataease [{8}]FIVE

Re:Re:Re:Re:Custom CDF and strings

Hi there,

thank you for this tutorial, very useful and informative. I went through it and it seems pretty clear. I have just one question regarding the memory space taken by the input variables. In the CDF form there are five types defined in the drop-down menu: int, long, float, double, string. We have to map those to C variables, so, in my understanding, it should be:

DataEaseCBytes
INTINT4
LONGLONG4
FLOATFLOAT4
DOUBLEDOUBLE8
STRINGLPCSTR4

We have to take in mind this table when "mangling" parameters in DLL functions.

Are those values correct?

Regards.

Written by George Washington 23/06/15 at 07:45:14 Dataease [{8}]FIVE

Re:Re:Re:Re:Re:Custom CDF and strings

Arul. I think you have just proven my point here.

With DataEase you can get the default printer name and also set a default printer automatically as following:

Step 1:
Create following CDFs:

1- Function Name: GetDefaultPrinterA
CDF Library Name: Winspool.drv
Return Type: Long
Parameters:
1.Name: prtNameBuffer Type: Long
2.Name: prtNameSizeBuffer Type: Long

2- Function Name: SetDefaultPrinterA
CDF Library Name: Winspool.drv
Return Type: Long
Parameters
1.Name: prtName Type: String

3- Function Name: RecordSave
CDF Library Name: dfwacts.dll
Return Type: Int

After creating those CDFs, please close the application and reopen it again (to register the CDFs).

Step 2:
Create a new form with one field.
Form name: GetDefaultPrinter.
Field name: ‘DefaultPrinterName’ data-type: Text 255, Prevent Entry

Create a button with caption “Click Here to Get the Default Printer Name”.
Right-click the button and select OML from the pop-up menu and type the
following:

define “BufName” text 49 .
define “BufLen” text 4 .
define “prtName” number .
define “prtLen” number .
define “retval” number .

BufName := “1234567890123456789012345678901234567890123456789” .
Buflen := “1” . — Ascii 49

prtName := addressof(BufName) .
prtLen := addressof(BufLen) .

retval := GetDefaultPrinterA( prtName, prtLen ) .
DefaultPrinterName.Value := BufName .
retval := RecordSave () .

Now save the form and return to the User View (or press F4). In the user view click the button to get your default printer name and place it into the field.

Step 3:
Create a new form with one field:
Form name: SetDefaultPrinter
Field name: “PrinterName” , data-type: text and length 255

Create a button with caption “Type the Printer Name You want to set. Click this button to set the Default Printer”. Right-click the button and select OML from the pop-up menu and type the following:

define “retval” number .

retval := RecordSave () .

retval := SetDefaultPrinterA (PrinterName.Value) .

Now save the form and return to the User View (or press F4). In the user view enter the printer name exactly as it appears under control panel >> Printers and Faxes.

SetDefaultPrinterA IS a CDF.... 

addressof() is one of the very few functions that they found time to make from 5.x to 7.1.... and it doesn't something that is illegible for the majority of our users.

Addressof function

CDF's are "external" methods and they expect real addresses. Moreover, they expect addresses to certain data types, e.g. LPDWORD or LPWORD, which are not the same because they point to datum of different lengths. DataEase 7 contains an addressof function which returns the real address of data to the DataEase process memory.

For example, assume that a CDF named SqCDF is registered with the application. SqCDF accepts a pointer to a number, and it multiplies that number by itself.

Then the script:

define "Arg" Number .define "Res" Number .assign Arg := 10 .assign Res := SqCDF(addressof(Arg)) .message Arg window .

Â?will display the number 100 in a message window. But notice that we are displaying the variable Arg, which has not had any Â?assignÂ? statements made to it. Instead the new value has been directly written into the memory address of Arg.

Note: The example above assumes that the CDF SqCDF treats passed pointer as a pointer to an 8-byte double precision number.

LIke I said, to do this you need a completely different kind of programming skill than DataEase aim for and simply showcase that they people in charge did not understand the target group for the product. 

It is/was called DataEase after all.

If you have read the blog you have got that we finally implemented this in 8.5

SetState("DefaultPrinter","PrinterName")

GetSate("DeafultPrinter") -- return default printer name.

I would say that that is a little more DataEasey then the example above.

Written by DataEase 11/06/15 at 13:43:04 Dataease [{8}]FIVE

Re:Re:Re:Re:Re:Custom CDF and strings

Hi there,
I am playing with CDF and I am cleraly missing something. Followed the part 2 tutorial and everything went ok: I can pass parameter to a function in an externel ddl and get a result. So, next step was to write my own function. I began with a small test function to calculate the area of a circle, given the radius. So, in the ExampleCDF.h file I adde the following lines:

EXAMPLECDF_API double mycircle(double radius);
#pragma comment(linker, "/EXPORT:mycircle=_mycircle@8")

And in the ExampleCDF.cpp:

EXAMPLECDF_API double mycircle(double radius)
{
double c_area = 3.14 * radius * radius ;
return c_area ;
}

Finally I registered the function in DataEase in the Custom Functions table.

Then I ran a simple test, I created a procedure as follows:

message mycircle(10) window .

And the result of the function is... 10

After many attempts to get the correct result, I modified the function as follows:

ExampleCDF.h

EXAMPLECDF_API LPCSTR mycircle(double radius);
#pragma comment(linker, "/EXPORT:mycircle=_mycircle@8")

ExampleCDF.cpp

EXAMPLECDF_API LPCSTR mycircle(double radius)
{
double c_area = 3.14 * radius * radius ;
sprintf_s(_returnbuffer, 256, "%f", c_area);
return _returnbuffer;

}

And the result was the correct one, 314.

Please, shed some light on this mistery.

Regards.

Written by George Washington 24/06/15 at 08:07:02 Dataease [{8}]FIVE

Re:Re:Re:Re:Re:Re:Custom CDF and strings

I see what you were saying.

But, some clients already feeling DataEase 8.x developer is way advance than previous versions.
I am ok with this :-)

Written by Jeyarajah Arulrajah 12/06/15 at 18:57:43 Dataease [{8}]FIVE

Re:Re:Re:Re:Re:Re:Custom CDF and strings

up

Written by George Washington 03/07/15 at 08:43:57 Dataease [{8}]FIVE

Re:Re:Re:Re:Re:Re:Re:Custom CDF and strings

Our resident CDF expert has been on holiday but will be back next week.

Written by DataEase 05/07/15 at 11:10:48 Dataease [{8}]FIVE