on 2015 Jul 05 8:28 AM
hello sir/madma
may i ask question about C/C++ build a api for powerbuilder to consume,i'd like write dll which powerbuilder could call in function which is defined int myfun(string ls_param1,ref string ls_param2) "mydll.dll;Ansil" ,i just cant figure out the ls_param2 in C++,if should write as
int myfun(char * theparm1,char** ls_param2) ?
do i have to use char ** in the second parameter?
thanks
regards
Ken
Request clarification before answering.
If you write the dll only for PowerBuilder, then writing a PBNI extension might also be an option,
You would have predefined types pbstring with get and set functions.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
thanks you ,i will find more information about PBNI later,but i have tried to build a dll for powerbuilder, i have failed,could you check what's wrong?i think i have two challenge of building the dll for powerbuilder,firstly is wchar_t * convert to char *,secondly is how to return a int and char * in a same time,i build the dll for cosuming the rest web service,so firstly i done the following test
i builded a dll in VC with the following code
int __stdcall testmyapi(char * tempstr, char ** retstring)
{
std::wstring wstrinvnum = L"1215265152";
std::wstring_convert<std::codecvt <wchar_t, char, std::mbstate_t>> converter(new std::codecvt<wchar_t, char, std::mbstate_t>("CHS"));
std::string narrowstr = converter.to_bytes(wstrinvnum);
size_t outputSize = wstrinvnum.length() + 1;
const char * str = new char[outputSize];
// char * tempstr = new char[outputSize];
str = narrowstr.c_str();
strcpy_s(tempstr, outputSize, str);
*retstring = tempstr;
return 0;
}
then i declare this dll in Powerbuilder
i declare it in global external function
function long testmyapi (string tempstr,ref string retstring) library "testdll.dll"
then i test this function in a button click event
string ls_tempstr,ls_src
long recode
recode= testmyapi(ls_src, ls_tempstr)
messagebox("",ls_tempstr)
however the messagebox didnt display the 1215265152 ,it has displayed the odd string
,when i click this button second time,the string has change to another odd string .
Here's an example and description of a Windows DLL call that uses both a string, and a reference to a string:
PB declaration:
Function long GetEnvironmentVariable(string lpName, ref string lpBuffer, long nSize) library "kernel32.dll" alias for "GetEnvironmentVariableW"
By using REF, it tells PB that the string can change. If it's not used, PB will use a copy of the string (or copy of any other value) as a throw away. This guarantees that the var you send will remain unchanged, even if it's a badly written DLL that may overwrite it by accident. Both are pointers to a string, one that can't change, one that is expected to be set by the DLL function.
Windows declaration (from MSDN):
DWORD WINAPI GetEnvironmentVariable( LPCTSTR lpName, LPTSTR lpBuffer, DWORD nSize);
LPCTSTR means Long Pointer to Constant Wide String (unicode)
LPTSTR means Long Pointer to Wide String (unicode)
alternate declaration:
long WINAPI GetEnvironmentVariable( const char *lpName, char *lpBuffer, long nSize);
Always make sure you have made the REF String var be big enough in PB to hold the string generated in the DLL. Use the space function to pre-allocate it.
Hope this helps,
Brad
thanks for your tips,i have resolve the problem with that.however the LPCTSTR and LPTSTR is a variable in MFC,not the win32,it seems that will be more complicate to write a dll that relative to MFC,i ever searched some web page that it's a little bit different to call the MFC in dll,so im not sure how to use it.
now i change the C++ code,i have a problem with this dll in pb 12.5,however it works fine in POWERBUILDER version 9,i just got the odd string in pb 12.5 with which defined in global external function like
function long testmyapi (ref string retstring) library "testdll.dll"
,i tried to define in global external function like this
function long testmyapi (ref string retstring) library "testdll.dll;Ansi"
unfortunatery,i just got the program occured the bad runtime error.
int __stdcall testmyapi(char * tempstr)
{
std::wstring wstrinvnum = L"1215265152";
std::wstring_convert<std::codecvt <wchar_t, char, std::mbstate_t>> converter(new std::codecvt<wchar_t, char, std::mbstate_t>("CHS"));
std::string narrowstr = converter.to_bytes(wstrinvnum);
size_t outputSize = narrowstr.length() + 1;
const char * str = new char[outputSize];
str = narrowstr.c_str();
strcpy_s(tempstr, outputSize, str);
//delete[] str;
return 0;
}
i declare it in global external function
function long testmyapi (ref string retstring) library "testdll.dll"
then i test this function in a button click event
string ls_tempstr
long recode
recode= testmyapi( ls_tempstr)
messagebox("",ls_tempstr)
does sombody know what's wrong?
regards
Ken
Just to be clear on a few things.
C/C++ provides for two different sizes of strings, ANSI and Unicode;
LPTSTR and LPCTSTR are defined in WINNT.H, and are not part of the MFC, they're just standard ways of declaring and easily reading type definitions. Winnt.h should be included in your VC installation.
wchar_t *str - unicode declaration
char *str - ansi declaration
PB9 uses ANSI, PB10 and up uses Unicode.
If you need to use PB9, then the declaration you have will work ok (as you've seen).
If you only need to use pb 12.5, then you don't need to use the ;ANSI at all, just redefine your function to use wchar_t as it's argument type.
Try this for pb 12.5:
int __stdcall testmyapi(wchar_t * tempstr, size_t maxlen)
{
wchar_t *wstrinvnum = L"1215265152";
RtlStringCbCopy(tempstr, maxlen, wstrinvnum);
return 0;
}
On the PB side:
Function TestTheDLL(string InvNum, ulong MaxLen) library "testdll.dll"
Code:
String ls_invnum
ls_invnum = space(22) // string is 10 chars long (in the C++ code), 11 when you include null terminator, so double it for unicode storage
TestTheDLL(ls_invnum, 22)
messagebox("And the result is", ls_invnum)
If you need to call the dll from both PB 9 and pb 12.5, then create 2 functions that act as wrappers to the main function that does the work. The PB9 version of the function will do the string conversion after calling the single , the 12.5 version will just return the result in the return string.
// function that actually does work
wchar_t *DoStuff()
{
return L"1215265152";
}
// wrapper for PB9
int __stdcall TestMyAPI9(char *tempstr, size_t maxlen)
{
std::wstring_convert<std::codecvt <wchar_t, char, std::mbstate_t>> converter(new std::codecvt<wchar_t, char, std::mbstate_t>("CHS"));
std::string narrowstr = converter.to_bytes(DoStuff());
size_t outputSize = narrowstr.length() + 1;
if(outputSize > maxlen) outputSize = maxlen;
const char * str = new char[outputSize];
str = narrowstr.c_str();
strcpy_s(tempstr, outputSize, str);
//delete[] str;
return 0;
}
// wrapper for pb12.5
int __stdcall TestMyAPI125(wchar_t * tempstr, size_t maxlen)
{
RtlStringCbCopy(tempstr, maxlen, DoStuff());
return 0;
}
Warning: None of this code is tested, but should be correct in concept.
hello sir
thanks for your help,im appreciate,i have resolved this issue,i have defined wrong in PB 12.5,
i should define like this
function long testmyapi (ref string retstring) library "testdll.dll" alias for "testdll.dll;Ansi" instead of function long testmyapi (ref string retstring) library "testdll.dll;Ansi"
thanks all!
regards
Ken
Try this:
short WINAPI myfunc(LPSTR lpParam1,LPSTR lpParam2)
LPSTR indicates a by ref string. I am pretty sure C doesn't distinguish between updateable and non-updateable strings. It is just a memory pointer to a char array.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Ken,
The responses from Bruce and Roy in this post should help you out.
Http://codeverge.com/sybase.powerbuilder.objects/calling-c++-function-in-pb/891348
Hth,
Mark
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
hello mark, thanks,i have checked the link,but i still confused that char ** means string array or refrenece a string pararmeter in POWERBUILDER,what do you think?
it sounds like i should use char ** as parameter in C++ if i'd like to reference the string In Powerbuilder to cosume the C++ dll
regards
Ken
| User | Count |
|---|---|
| 5 | |
| 5 | |
| 4 | |
| 3 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 1 | |
| 1 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.