Create DLL for other languages

Hi all,

I have some DLLs generated by C10. They work perfectly fine when called from other Clarion programs. However, if I call the same DLLs from NodeJS, they don’t seem to work, the calling program shuts down. Any idea?

My clarion app:

MAP
tester(STRING, LONG),BYTE,NAME(‘tester’)
END

tester FUNCTION(inString, inLong)

ReturnValue BYTE(1)

CODE

message('Inside DLL: ' & inString & ' / ' & inLong)

RETURN ReturnValue

This is not so simple. At least your export function must have explicit calling convention C or PASCAL.
STRING type is not a good choice for parameters, use (*CSTRING) instead.
Also I suspect that Clarion runtime should be linked to the dll or be placed in same folder.
Also read AttachThreadToClarion topic in the help.

Pascal calling convention is preffered (because Windows API uses it).
Also you must avoid cross-calling, for example Clarion - NodeJS - Clarion or NodeJs Clarion - NodeJS. And a lot of other things… :slight_smile:
I agree with Mike_Duglas: this is not so simple…

Should also use the NAME attribute to get around name mangling.

Thanks all for your hints, I figured it out now.

MAP
proc_name(LONG),C,NAME(‘proc_name’) !accepting the address of a cString from other programs
END

proc_name PROCEDURE(adr_CString)

myStr &CSTRING

CODE
mystr &= (adr_CString)

If you add a parameter for the length, you can do something like this:

mystr &= (adr_CString) & ‘:’ & Length

Otherwise, you can run into trouble on some functions.

Hi

Apologies for opening this old discussion, but this is something we have started pursuing recently.

We are developing new frontends in C# but most of our business logic is in Clarion.

We have had some success with the following procedures:
AddNumbers(long Num1, long Num2), long, C, name(‘AddNumbers’)
AddNumbersV2(*long pNum1, *long pNum2), long, C, name(‘AddNumbersV2’)
TestStringV1(BSTRING pStrA,BSTRING pStrB),BSTRING,C,name(‘TestStringV1’)
TestStringV2(*BSTRING pStrA,*BSTRING pStrB),BSTRING,C,name(‘TestStringV2’)

Passing QUEUE and GROUP structures seems significantly more challenging eg.
TestGroupV1(*mGroup1 pGroup)ULONG,C,name(‘TestGroupV1’)
TestQueueV1(*mQueue1 pQueue)ULONG,C,name(‘TestQueueV1’)

My question therefore is whether passing these structures is at all possible from Clarion to eg. C#?

Regards

Reggie

Have you tried (LONG pAddress)?

If you are passing *Group I think you want RAW on the prototype or the compiler will also pass the Size as an extra Long parameter.

You probably want to pass the size yourself as a parameter so your function can verify the Struct is the size it is expecting or larger. You see this very often on Windows API calls.

The Queue internals are not published so I doubt you can pass a queue in any easy way. You could make a big array and pass that. Maybe load it into a memory mapped file if that’s something that .Net can access easily.

Might as well be json.

see Using Groups with .Net Com Controls Part 1 - code / Interop - ClarionHub

Notice the [StructLayout(LayoutKind.Sequential, Pack = 1)] attribute on the struct

My approach to sending Queues from CW to C#
In Clarion: Serialize to json & put into a MemoryMappedFile (MMF) (using APIs)
Then I RUN my C# EXE
In C#: I read the contents using System.Io.MemoryMappedFiles and a StreamReader
then deserialize using NewtonSoft Json

I used a MMF because I was loading data then RUN()'ing the C# .EXE
For a direct call, I imagine it would be far easier to pass the data as a BSTRING

BTW, this is an interesting subject to many, and seems like it deserves it’s own appropriately titled thread.