using PB-made dll in MSVSC++12/13 project - unicode problem
using PB-made dll in MSVSC++12/13 project - unicode problem
hi all,
i made a dll with PB and tested it with PB (OpenLibrary, GetFunction, CallFunctionFast), so i know it works at least in there. Now I want to use the DLL in a MSVSC++12/13 project, however I am not sure how to do this correctly. my steps so far:
- Properties>Linker>General>Additional Library Directories: path to both my lib and dll
- Properties>Linker>Input>Additional Dependencies: added the name of my .lib file
my procedure names from the DLL are still not highlighted, so I thought i'd write a header file. is that correct&necessary? if so, how is it supposed to look? I have a bunch of "extern"al function declarations, but I am unsure about the variable types, for instance is a PB string a char* or a string, is a PB-int equivalent to a c++-int, and so forth.
with the custom header file, I am getting an "unresolved external symbol LNK2019" error on my first custom function call.
thanks in advance
i made a dll with PB and tested it with PB (OpenLibrary, GetFunction, CallFunctionFast), so i know it works at least in there. Now I want to use the DLL in a MSVSC++12/13 project, however I am not sure how to do this correctly. my steps so far:
- Properties>Linker>General>Additional Library Directories: path to both my lib and dll
- Properties>Linker>Input>Additional Dependencies: added the name of my .lib file
my procedure names from the DLL are still not highlighted, so I thought i'd write a header file. is that correct&necessary? if so, how is it supposed to look? I have a bunch of "extern"al function declarations, but I am unsure about the variable types, for instance is a PB string a char* or a string, is a PB-int equivalent to a c++-int, and so forth.
with the custom header file, I am getting an "unresolved external symbol LNK2019" error on my first custom function call.
thanks in advance
Last edited by broozar on Mon Sep 28, 2015 9:05 am, edited 1 time in total.
Re: using PB-made dll in MSVSC++12/13 project
i now have
does that look correct to you? it compiles, but for some reason the string i plug into const char* parametername does not appear to get through to the plugin.
Code: Select all
extern "C" {
int __stdcall functionname ( const char* parametername, [...]);
[...]
}
Re: using PB-made dll in MSVSC++12/13 project
ok, i really think the problem lies in my "const char* parametername". I try to pass a windows file path to my PB-made DLL ("D:\something\somethingelse"), and since backslashes have to be escaped in C/C++ strings, I use ("D:\\something\\somethingelse"). However the DLL does not find the folder.
with my own dll test program written in PB, i can successfully call my path using CallFunctionFast(function, @"D:\something\somethingelse"), completely without escaping anything.
what's going on here? any ideas?
with my own dll test program written in PB, i can successfully call my path using CallFunctionFast(function, @"D:\something\somethingelse"), completely without escaping anything.
what's going on here? any ideas?
Re: using PB-made dll in MSVSC++12/13 project
First, ensure that the DLL is actually receiving the properly formatted path string. Give this example a try:broozar wrote:I try to pass a windows file path to my PB-made DLL ("D:\something\somethingelse")...However the DLL does not find the folder.
1. Create a test DLL, DLL Example, as follows:
Code: Select all
; DLL Example.dll / DLL Example.lib
ProcedureDLL MyFunction(filePath.s)
MessageRequester("Received String:", filePath, 0)
EndProcedure
Code: Select all
#pragma comment (lib, "DLL Example") //no file extension required
extern "C" __declspec(dllimport) void _stdcall MyFunction(char* filePath);
Code: Select all
MyFunction("D:\\something\\somethingelse\\*.*");
1. The DLL should be compiled with UNICODE disabled.
2. Both the PureBasic DLL and the C/C++ EXE must be compiled under the same architecture (either both 32bit, or both 64bit).
3. Both the generated .DLL and .LIB files should be in the VS2013 project source folder (no additional link/reference settings required).
Hope it works!

Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project
thanks for your reply!

if i disable unicode, i get at least the file path right. however i believe i do need that flag: the library is actually a translation helper for 26 languages, including non-ascii sets like chinese, russian, korean, and thai. i read my strings from utf-8 encoded XML files and need to return similarly encoded strings.
to clarify, the architecture of it all is this:
- one DLL (made with MSVS) acts as a plugin for another program. it sends the file path string as a parameter to the PB-made DLL as part of the init procedure
- this PB-made DLL gets the string, looks the folder up, and hopefully finds some utf-8 XML files in there. those files are read in and transformed
- the MSVS DLL can now call the PB-DLL and ask for random strings which could include non-ascii characters: [A-Z_] in, [.] out.
how can the absence of the unicode flag be reconciled with my need for utf-8 strings?
and: why does it work with unicode if i do not call the same thing from a MSVS DLL, but another PB program through CallFunctionFast?
PS: I already went through the MSVS project configuration properties > general > character set and switched it to unicode, no change. the "chinese" path string is the same.
uh-oh. that was unexpected. with the unicode flag set, i get this lovely string for a file path:TI-994A wrote:broozar wrote:1. The DLL should be compiled with UNICODE disabled.

if i disable unicode, i get at least the file path right. however i believe i do need that flag: the library is actually a translation helper for 26 languages, including non-ascii sets like chinese, russian, korean, and thai. i read my strings from utf-8 encoded XML files and need to return similarly encoded strings.
to clarify, the architecture of it all is this:
- one DLL (made with MSVS) acts as a plugin for another program. it sends the file path string as a parameter to the PB-made DLL as part of the init procedure
- this PB-made DLL gets the string, looks the folder up, and hopefully finds some utf-8 XML files in there. those files are read in and transformed
- the MSVS DLL can now call the PB-DLL and ask for random strings which could include non-ascii characters: [A-Z_] in, [.] out.
how can the absence of the unicode flag be reconciled with my need for utf-8 strings?
and: why does it work with unicode if i do not call the same thing from a MSVS DLL, but another PB program through CallFunctionFast?
PS: I already went through the MSVS project configuration properties > general > character set and switched it to unicode, no change. the "chinese" path string is the same.
Re: using PB-made dll in MSVSC++12/13 project
In that case, try this:broozar wrote:...however i believe i do need that flag...
Code: Select all
ProcedureDLL MyFunction(filePath.s)
filePath = PeekS(@filePath, -1, #PB_UTF8)
MessageRequester("Received String:", filePath, 0)
EndProcedure

Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project - unicode prob
great, that seems to be a step in the right direction. i now override all string-arguments in the procedures with your PeekS-UTF8 tip, and it seems to work: all strings get to the DLL intact.
since i also have strings for return values, i need to do the same thing in reverse, as the output is equally garbled right now. i tried the same PeekS with UTF-8 in ProcedureReturn, however it returns a number... any tips?
all those changes also broke the DLL tester i wrote in PB. now the path is broken in there - not chinese, but stops after the first character. is there no universal solution, like working in unicode from front to back?
PS: i read on stackoverflow that windows/.net unicode is really utf-16, and so my utf-8 strings are causing problems. what confuses me is that the error occurs before i ever open any utf-8 encoded files, the problem occurs when sending a string from one unicode DLL to the next. i'd love to understand why this happens. when PB talks about unicode, do they mean UTF-8, UTF-16, or does it depend on the platform, like UTF-16 for Windows and UTF-8 for Linux?
since i also have strings for return values, i need to do the same thing in reverse, as the output is equally garbled right now. i tried the same PeekS with UTF-8 in ProcedureReturn, however it returns a number... any tips?
all those changes also broke the DLL tester i wrote in PB. now the path is broken in there - not chinese, but stops after the first character. is there no universal solution, like working in unicode from front to back?
PS: i read on stackoverflow that windows/.net unicode is really utf-16, and so my utf-8 strings are causing problems. what confuses me is that the error occurs before i ever open any utf-8 encoded files, the problem occurs when sending a string from one unicode DLL to the next. i'd love to understand why this happens. when PB talks about unicode, do they mean UTF-8, UTF-16, or does it depend on the platform, like UTF-16 for Windows and UTF-8 for Linux?
Re: using PB-made dll in MSVSC++12/13 project - unicode prob
1. Change the PureBasic DLL code as follows:broozar wrote:...since i also have strings for return values, i need to do the same thing in reverse, as the output is equally garbled right now.
Code: Select all
ProcedureDLL.s MyFunction(filePath.s)
Static returnString.s
returnString = "PureBasic DLL: the file path is " + PeekS(@filePath, -1, #PB_UTF8)
ProcedureReturn returnString
EndProcedure
Code: Select all
extern "C" __declspec(dllimport) char* _stdcall MyFunction(char* filePath);
Code: Select all
char* response = MyFunction("C:\\something\\something\\*.*");
MessageBox(NULL, LPCWSTR(response), L"From the DLL", MB_OK);

EDIT: defined the return string as static, per Fred's advice.

Last edited by TI-994A on Tue Sep 29, 2015 4:05 am, edited 2 times in total.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project - unicode prob
If you return a string, you should return a static string, or it could have problem as the string has been freed before leaving the procedure.
Re: using PB-made dll in MSVSC++12/13 project - unicode prob
Thanks for the pointer, Fred. Something that I'm not aware of.Fred wrote:If you return a string, you should return a static string, or it could have problem as the string has been freed before leaving the procedure.

Code edited accordingly.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project - unicode prob
It's still wrong, you have the return only the static string 

Code: Select all
ProcedureDLL.s MyFunction(filePath.s)
Static returnString.s
returnString = "PureBasic DLL: the file path is " + PeekS(@filePath, -1, #PB_UTF8)
ProcedureReturn returnString
EndProcedure
Re: using PB-made dll in MSVSC++12/13 project - unicode prob
thanks for all the help! unfortunately, I have to be difficult as I can't get it to work. since it's no secret what I am working on, i will share some more code.
from the header:
my original question was about "const char* XMLFOLDER", which is the filepath that was not transmitted correctly. now, pg_translate and pg_translateCompound are giving me trouble, as they return nonsense.
from the "host" DLL:
- I feed (ASCII only) sLangcode and sPolyglotCode to the dll, and convert those strings into const char* through the host program function GetStringValue()
- those are then plugged into the pg_translate function as defined in the header
- since I need to send the result back to the host program through SetStringValue which only accepts const char*, the return of pg_translate is also supposed to be of that type
from the PB DLL:
The PB docs for DLLs state that all outgoing strings need to be declared as globals, but now with the static declaration in the function, is that still true? is there a possible conflict?
PS: the line MessageBox(NULL, LPCWSTR(response), L"From the DLL", MB_OK); does not seem to work at all for me. LPCWSTR does not accept the type from "response" as argument, and the literal L also throws an error.
EDIT: just saw fred's reply, "ProcedureReturn pg_returnTranslatedString" also gives no good result
from the header:
Code: Select all
extern "C" {
__declspec(dllimport) int __stdcall pg_init (const char* XMLFOLDER, const char* SCHEME, int VERSION);
__declspec(dllimport) int __stdcall pg_isLanguageAvailable(const char* LANGCODE);
__declspec(dllimport) const char* __stdcall pg_translate (const char* LANGCODE, const char* CODESTRING, int bLC);
__declspec(dllimport) const char* __stdcall pg_translateCompound (const char* LANGCODE, const char* CODESTRING, int bLC);
}
from the "host" DLL:
Code: Select all
//type conversion
const char* lc = sLangcode.GetStringValue();
const char* pc = sPolyglotCode.GetStringValue();
bool bl = bLowercase.GetBooleanValue();
const char* trans = pg_translate(lc, pc, bl);
stranslatedString.SetStringValue(trans);
- those are then plugged into the pg_translate function as defined in the header
- since I need to send the result back to the host program through SetStringValue which only accepts const char*, the return of pg_translate is also supposed to be of that type
from the PB DLL:
Code: Select all
; -- EXPORT -------------------------------------------------
; translated string to return
Global pg_returnTranslatedString.s = ""
; -- LOCALS --------------------------------------------------
Structure pg_langstruct
langstring.s
version.i
location.s
EndStructure
Structure pg_dict
Map dict.s()
EndStructure
Global NewMap availableLanguages.pg_langstruct()
Global NewMap languageDict.pg_dict()
Global pg_bInit = 0
; -- more preocedures here -> shortened
; translate string from code string
ProcedureDLL.s pg_translate(LANGCODE.s, CODESTRING.s, bLC.i)
Static pg_returnTranslatedString.s
LANGCODE = PeekS(@LANGCODE, -1, #PB_UTF8)
CODESTRING = PeekS(@CODESTRING, -1, #PB_UTF8)
If pg_bInit = 1
If FindMapElement(languageDict(), LANGCODE)
If bLC = 0
pg_returnTranslatedString = languageDict(LANGCODE)\dict(CODESTRING)
Else
pg_returnTranslatedString = LCase(languageDict(LANGCODE)\dict(CODESTRING))
EndIf
Else
pg_returnTranslatedString = "NOCODE"
EndIf
Else
pg_returnTranslatedString = "NOINIT"
EndIf
ProcedureReturn PeekS(@pg_returnTranslatedString, -1, #PB_UTF8)
EndProcedure
PS: the line MessageBox(NULL, LPCWSTR(response), L"From the DLL", MB_OK); does not seem to work at all for me. LPCWSTR does not accept the type from "response" as argument, and the literal L also throws an error.
EDIT: just saw fred's reply, "ProcedureReturn pg_returnTranslatedString" also gives no good result
Re: using PB-made dll in MSVSC++12/13 project - unicode prob
A little vague, especially when you seem to be dealing with multiple libraries. A little more code would help to put things in some perspective; at the very least, the full or working portions of the procedures involved, along with all their global dependencies. Alternatively, if you'd like, just zip the whole project up.broozar wrote:...I can't get it to work. since it's no secret what I am working on, i will share some more code.
I'd be happy to look it over, and try to help out to the best of my abilities.

Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project - unicode prob
Right; the temp string as well.Fred wrote:It's still wrong, you have the return only the static string

Thanks again, Fred.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: using PB-made dll in MSVSC++12/13 project - unicode prob
Here are some points based on what you've provided.
When the pg_translate() function is called here:make sure that the DLL is receiving the values lc, pc, bl properly; perhaps by using message requesters to display them:If they are, simply return the result like so:
I'm not familiar with the string library that you're using, but you should be able to assign the returned string directly to a string variable.
When the pg_translate() function is called here:
Code: Select all
const char* trans = pg_translate(lc, pc, bl);
stranslatedString.SetStringValue(trans);
Code: Select all
ProcedureDLL.s pg_translate(LANGCODE.s, CODESTRING.s, bLC.i)
Static pg_returnTranslatedString.s
MessageRequester("Param 1:", PeekS(@LANGCODE, -1, #PB_UTF8), 0)
MessageRequester("Param 2:", PeekS(@CODESTRING, -1, #PB_UTF8), 0)
MessageRequester("Param 3:", Str(bLC), 0)
...
...
Code: Select all
...
...
ProcedureReturn pg_returnTranslatedString
EndProcedure
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 
