Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Writing c# dll for powerbuilder, what am I missing?

Status
Not open for further replies.

Lex28

Programmer
Apr 2, 2008
2
GB
Hi guys,

I have been trying to get powerbuilder to use custom dlls I have created in C#. I have created a simple c# dll with this code-

using System;
using System.Text;

namespace DllTest
{
public class Numbers
{
public int AddNumbers(int num1, int num2)
{
int result = num1 + num2;
return result;
}
}
}

I then signed it with a strong key moved it to the system32 folder and successfully registered it with the GAC. (as a off note I have created a c# program that successfully uses this dll from from the GAC).

I then added the following code to the global external functions-

Function int AddNumbers(int num1, int num2)
Library "DllTest.dll"

How ever when ever i try to call this function I get this message "Error calling external function AddNumbers ...."

Anyone got any ideas where I am going wrong, I have been at this for a couple of days now!!

Thanks in advance.
 
I wish I could help on this topic... But I am in the "same boat", only I don't really have a need to use this. I just would like to know how!
 
hi theKlOwn,

Good to get a reply about powerbuilder even if you don't know what's up, was starting to think that I was the only person using powerbuilder ;)

I have however made some progress on this matter, although not through the global assembly cash i'm affraid :(

I have managed to create a dll in c# and get power builder to use it, and shall pop my code here in case it helps anyone.

ok so the code to create the dll is as follows :-

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;

namespace WBEmail
{
public class WBSendEmail
{
/// <summary>
/// This function is used to send email
/// </summary>
public static bool sendSmtpEmail(string smtpClientName, string fromAddress, string toAddress, string subject, string msgBody)
{
SmtpClient smtpClient = new SmtpClient(smtpClientName);
MailMessage mailMsg = new MailMessage();
MailAddress fromEmail = new MailAddress(fromAddress);
MailAddress toEmail = new MailAddress(toAddress);
mailMsg.Subject = subject;
mailMsg.From = fromEmail;
mailMsg.To.Add(toEmail);
mailMsg.Body = msgBody;
smtpClient.Send(mailMsg);
return true;
}
}
}

The important thing to note about this code is the static property, for the way I reference the function in dll it is important to include this!!!

So didn't bother signing this with a strong key pair or inserting into the GAC as I have just referenced it in my powerbuilder winforms/webform .net applications.

I have moved the Dll inside of the PB aplication now ( not tested exactly where you can get away with having this, from somewhere I read either needs to be somewhere in the windows folder on the pb allpication folder for powerbuilder to be able to pick it up.)

With all windows closed on the target goto the propertys of the .net target and you can then brows to the dll with the [...] button.

Once this is done you can reference the function in your code via this meathod.

boolean result
string smtp
string fromAddress
string toAddress
string subject
string msgBody

smtp = "Tring3"
fromAddress = "alexis.coles@????.co.uk"
toAddress = "alexis.coles@????.co.uk"
subject = "Testing"
msgBody = "Testing WBEmail.dll"

#IF DEFINED PBDOTNET THEN
result = WBEmails.WBSendMail.sendSmtpMail(smtp, fromAddress, toAddress, subject, msgBody)

#END IF


IF result = true THEN
st_1.text = "Success"
else
st_1.text = "fail"
END IF

The important part here is the wrapper that the call sits in. the #IF DEFINED PBDOTNET means that the powerbuilder compiler will skip this code, which is good because it won't understand it! But when the .net compiler kicks in it will execute it as it is .net code!

Hope this helps pleople.

P.S. would still like to know how you can reference the dll through the external function method though. From my countless hours of googling I am starting to think that you need to put a COM wrapper in the DLL to make it interface with powerbuilders standard compiler but didn't really manage to get it working at all :(
 
Got bored, and tried a simple VB.net test on the topic. Quite simply, all I had to do was create a new COM class, insert my code/properties/functions/etc and save. Went to the properties for the solution, and on the compile tab ensured that expose to COM was checked, and then went to build/build solution.

Switched over to PB10.5, and opened the TreeView and selected the Components tab... ActiveX controls\.NET Category and scrolled down... There was my test dll!

In PowerScript I used the following code to test:

OLEObject obj_test

obj_test = CREATE OLEObject
IF obj_test.ConnectToNewObject( 'TestDLL.TestClass' ) = 0 THEN
MessageBox( 'Test Function...', String( obj_test.ReturnTwelve( ) ) )
END IF


Guess what... MessageBox containing the number 12 popped up. And I feared this was going to be a huge drawn-out process.
 
I have been trying the same. I am aware that registered COM objects are visible to Pb. What I want to do is have Pb (running 11.5 Enterprise) call functions in a native Win32 dll--not COM. I also want to go the other way: I want a Win32 exe (both native and .net) to call a function in a Pb generated dll. I've had limited success.

Scenario 1: Pb generates native Win32 exe & dll.

I created a simple app that includes separate pbl (called shared.pbl) with some trivial functions (including one that returns the string HelloWorld). The project builds to an exe and a separate dll. It works (clicking a button shows the text HelloWorld in a label).

In a separate Pb workspace I create a near identical app, but no shared.pbl. I declare an external function to reference the shared.dll from the first workspace:

function int GetSystemMetrics( int index ) library "user32.dll";
function int f_rtn_int( int number ) library "shared.dll";

running the app--clicking a button tied to GetSystemMetrics() works. Clicking a second button to access shared.dll fails with the "Error calling external function ..." message.

The only way I have been able to get the second app to work is to add the shared.dll under the library list tab on the target properties. However this seems to cause the contents of the dll to be embedded in the generated exe--I can delete shared.dll and the second app runs just fine!

How do I reference an external Win32 dll in Pb w/o having the dll embedded in the generated Pb code? Remember, shared.dll was generated by Pb in a separate workspace.

Scenario 2: .Net exe accesses a Pb generated dll

I next created a simple .net app (.net v2.0, vs2005) with parallel functionality to the Pb apps. I reference shared.dll:

[DllImport( "user32.dll" )]
static extern int GetSystemMetrics( int smIndex );
[DllImport( "shared.dll" )]
static extern string f_get_hello_world();

and try to call the HelloWorld function and I get the .net error:

Unable to find an entry point named 'f_get_hello_world' in DLL 'shared.dll'

Using an editor/dissasembler I discover that the function name has been mangled into "_getVtableInfo_f_get_hello_world@12". I tried different naming variations on the declaration and call w/o luck.

Is it possible to reference a native Win32 dll created by Pb from another language (c++, c#)? If so, how?


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top