Unable to pass string parameters to Clarion Dll from C#

Tags: #<Tag:0x00007fc0dbcde3f0>

I have a Clarion Dll and I need to call a procedure inside of it from C# (I have access to both of the codes).

It works perfectlly if I don`t try to pass any paramters to the procedure.

This is the actual Clarion code, it has nothing inside, I am using it just for testing purposes.

AtualizaEstoqueNovo_Teste PROCEDURE  (string pr)           ! Declare Procedure
    CODE

The procedure MAP declaration.

50A5C8 [email protected]

From the C# end, I am declaring an extern void function.

[DllImport("C:\\Tests\\48\\prog\\ss007.dll", EntryPoint = "[email protected]")]
    public static extern void ATUALIZAESTOQUENOVO_TESTE(string pr);   

I am calling it like any other function

ATUALIZAESTOQUENOVO_TESTE("");

It throws me the error “Unable to find an entry point named “[email protected]””

The funny thing is that if I try to do the same thing but without using any paramters, it works.

[DllImport("C:\\Tests\\48\\prog\\ss007.dll", EntryPoint = "[email protected]")]
    public static extern void ATUALIZAESTOQUENOVO_TESTE();

I really don`t know what I am missing.

Also, the C# code is inside a Windows Service, but I think that shouldn`t matter

I’m sure someone that has done this will jump in …

The name is case sensitive so you need “@Fsb” not upper “@FSB”. That is not your only problem…

A Clarion STRING is not the same as a C# String. You will want to use a CSTRING in Clarion and in C# Marshall it as an ANSI Null Terminated String.

Your Clarion type will change to below. You must pass by Address hence the * Asterisk. You need RAW or Clarion expects the CString Size as another parameter (hidden in Clarion code):

AtualizaEstoqueNovo_Teste PROCEDURE(*CString pr),RAW,PASCAL

The mangled export symbol name should be ATUALIZAESTOQUENOVO_TESTE
but check the MAP or EXP file to be certain. Remember it’s Case Sensitive.


A better alternative would be to use a BSTRING in Clarion and Marshal it as a Unicode BSTR from C#. RAW is not required on a BSTRING it only passes the address and no length (the length is built into the BSTR type).

AtualizaEstoqueNovo_Teste PROCEDURE(*Bstring pr),PASCAL

and the mangled export symbol name should be ATUALIZAESTOQUENOVO_TESTE
but check the MAP or EXP file to be certain.


Edit 2:00 pm
Added PASCAL per Oggy to correct these examples which removes @Fxxx from the mangled name. Also PASCAL is important for proper stack cleanup otherwise you’ll probably GPF on return to the caller.

Been that way couple of weeks ago. So, first of all, if you are using clarion composed dll in c# application, you MUST add pascal attribute to your exported dlls, procedures…
So, your procedure looks like: ```
AtualizaEstoqueNovo_Teste PROCEDURE (bstring pr),pascal. In that case you avoid to use exported flags: @FSB.
One more thing. If this is hand-coded project that you try to use in c# application? I also try this and neve succeeded. So better use application generator to create your procedures.

1 Like

And just one thing, your import code is:

[DllImport("C:\\Tests\\48\\prog\\ss007.dll"

but, it is much better, or mandatory, to use like [DllImport(@"C:\\Tests\\48\\prog\\ss007.dll" because you must point to the path where your dll is

… and third, as Carl wrote, if you are using string parameter, on clarion side that MUST be bstring.
On C# side you are declaring you clarion proc as:

const UnmanagedType MYSTRING1 = UnmanagedType.BStr; // marshaled bstring
[DllImport(V, EntryPoint = " ATUALIZAESTOQUENOVO_TESTE ")] // importing your dll with pascal entry point
static extern void ATUALIZAESTOQUENOVO_TESTE([MarshalAs(MYSTRING1)] string MYSTRING1);
and now, calling looks like:
public void TestClarion()
{
string passedstring = "Test to pass to clarion "; // string with value that you will pass to clarion
ATUALIZAESTOQUENOVO_TESTE(passedstring);
}

Didn’t knew that I had to add the PASCAL attribute, I`m gonna try that.

Thank you for all the answers, I’m gonna try again and see if it works now. I`ll be back latter to let you know if it worked.

this works perfectly, I must thanks to Graham Dawson who explain it to me.
For parameters other than string/bstring, all is simplier.

There are a lot of resources here on ClarionHub about working with C#/.net.
Search these out and review the topics.
https://clarionhub.com/search?q=.net

const UnmanagedType MYSTRING1 = UnmanagedType.BStr; // marshaled bstring

[DllImport(@"C:\\Test\\48\\prog\\ss007.dll", EntryPoint = "ATUALIZAESTOQUENOVO_TESTE")]
public static extern void ATUALIZAESTOQUENOVO_TESTE([MarshalAs(MYSTRING1)] string MYSTRING1);        

Using it this way worked perfectlly, thanks

2 Likes

… also, if you wish to return value from clarion to c#, use:

[DllImport(@"C:\\Test\\48\\prog\\ss007.dll", EntryPoint = "ATUALIZAESTOQUENOVO_TESTE")]
 [return: MarshalAs(MYSTRING1)] // mandatory
public static extern string ATUALIZAESTOQUENOVO_TESTE([MarshalAs(MYSTRING1)] string MYSTRING1); // this is function (string), not void anymore
and in code, like in clarion:
somestring =  ATUALIZAESTOQUENOVO_TESTE(yourstringparameter);
Of course, return parameter in clarion is bstring, so your declaration of clarion function would looks like;
AtualizaEstoqueNovo_Teste PROCEDURE (bstring pr),bstring,pascal
2 Likes

“.Net” works but is a bit small. Searching for “MarshalAs” or “DllImport” finds these results:

1 Like