-
Jan 13th, 2015, 03:46 PM
#1
Thread Starter
New Member
problems with external lib calls
First problem
With a c function definition
//////////////////////////////
#define VERSION "1.0.0"
__declspec(dllexport) const char* __stdcall GetVersion()
{
return VERSION;
}
/////////////////////////////
why a vb6 declaration like
Public Declare Function GetVersion Lib "mylib.dll" () As String
just crash?
Others functions work fine
************************************************************************************
Second problem
This same library if i use it from the VB6 IDE it works perfectly ( except for the above function ) but if i build the exe file it crash, i modified the optimizations in the compiler options and after setting the "No optimizations" option the exe file didnt crash, but now it doesnt load ACTIVEXs files which are not registered with regedit, before with just copying the activex in the same folder as the exe file it had worked fine.
Weirder yet
i do the dll callings inside a class that is inside another class, but if a do the callings from the parent class it works fine, something like this pseudocode
Declare LibDoSomething lib .........................
class class2
{
sub DoSomething ()
call LibDoSomething()
end sub
}
class class1
{
sub Something()
set c2 = new class2
call c2.DoSomething ''''''''''''''' Crash , in exe file not in IDE
call LibDoSomething '''''''''' Not crash in exe file nor in IDE
end sub
}
call Something
somebody has any idea where can be the problem?
Thanks
-
Jan 13th, 2015, 04:03 PM
#2
Re: problems with external lib calls
Just a wild guess, but VB may be expecting a null terminated string. I don't know C well enough to know if "VERSION" is null terminated in your char* array?
-
Jan 13th, 2015, 04:21 PM
#3
Re: problems with external lib calls
Originally Posted by edmontreal
First problem
With a c function definition
//////////////////////////////
#define VERSION "1.0.0"
__declspec(dllexport) const char* __stdcall GetVersion()
{
return VERSION;
}
/////////////////////////////
why a vb6 declaration like
Public Declare Function GetVersion Lib "mylib.dll" () As String
just crash?
A 'const * char' in C is not allowed to be freed on the side of the caller...
(which IMO is the case with your: Public Declare Function GetVersion Lib "mylib.dll" () As String)
Better to declare:
Code:
Public Declare Function GetVersion Lib "mylib.dll" () As Long)
... then followed by copying the Bytes over from the returned (const) Pointer.
As for your other problems, see if those go away after you fixed the "Version-String-Problem" -
if these other problems remain persistent - then more info is necessary (which C-Dll or C-Source you are using,
and what declarations you have on the VB-end).
Olaf
-
Jan 13th, 2015, 06:35 PM
#4
Re: problems with external lib calls
Originally Posted by Schmidt
A 'const * char' in C is not allowed to be freed on the side of the caller...
Olaf
Olaf, for my own better understanding, I thought that when C (or whatever language) declared a function as StdCall, then caller/callee stack corruption was not an issue any longer? If that's true, then not terminating the string may be the reason for the crash. In either case, I agree that once this is resolved, the other problems probably go away also
-
Jan 13th, 2015, 08:10 PM
#5
Re: problems with external lib calls
Originally Posted by LaVolpe
Olaf, for my own better understanding, I thought that when C (or whatever language) declared a function as StdCall, then caller/callee stack corruption was not an issue any longer? If that's true, then not terminating the string may be the reason for the crash. In either case, I agree that once this is resolved, the other problems probably go away also
The const keyword in C has nothing to do with __stdcall or __cdecl calling-conventions.
It's more about: "responsibilities with regards to allocations behind pointers".
C-internally the C-compiler can throw warnings or even compile-errors,
when a declared "const-char-pointer" (e.g. those pointing to a static allocation,
as a String-Literal) is either attempted to be overwritten by a strcpy -
or attempted to be freed or attempted to be re-allocated.
It's a protection-mechanism for (usually) static allocations (works also for dynamic allocations, but less often used this way).
In VB we have everything on "full-automatic" - (B)Strings are auto-freed when they
go out of scope, String-Consts can be passed ByRef into another function,
overwritten there - but on return will "magically get their old Const-Value".
In C one needs to take care about such things oneself.
And declaring something:
const char *
instead of only:
char *
will help the C-compiler a bit, to identify "issues" and offer a bit more protection -
and in case of exported functions and parameters, a const-description is telling
the user on the outside, that it is "not his business to free the allocation behind
the handed-out string-pointer himself".
Whereas when StringPointers are returned to the caller which
are *not* "marked const", it's (usually) the responsibility of the caller who
received such allocations behind pointers, to free them when he's done.
The Declaration as it is currently will force VB to make a freeing-attempt
(unrelated to __stdcall-stack-issues) on the returned static string-pointer-allocation,
and thus causing a crash.
In case the VB-Declare for the function shall remain as it currently is in the first posting,
then the C-function would need to be changed to e.g.:
Code:
#define VERSION "1.0.0"
__declspec(dllexport) char* __stdcall GetVersion() //note that we defined char* and not 'const char*'
{
char *new_str = malloc(128); //dynamically allocate more than large enough for our-demo purpose
strcpy(new_str, VERSION ); //copy-over from the static allocation to the dynamic one
strcat(new_str, "_xyz" ); //just to show how appending another static literal works
return new_str; //return the dynamic allocation to VBs ANSI-mechanism, which will auto-free it
}
The above should work - but there's a small bug (which doesn't exist in VBs ANSI-Automatic
for ByVal-String-Params) - the call on the VB-Side will not crash, but VB does the wrong
Len-Calculation in the ANSI-to-W-conversion - and appends the ZeroTerminator-Char as
part of the String-content, so these returned C-Dll-String-Values are all exactly 1 (W)Char too long.
So in my own Dll-Bindings I always use Declarations with a Long-(Ptr) return-value at the VB-side -
and handle the copy-over into a BSTR myself - and depending on const or not const in the
C-header-declaration, I don't free the pointer afterwards or not - *not* freeing is mandatory
in case of const return-values - and freeing of "non-const-marked char-return-values" sometimes
depends, but is usually our responsibility at the VB-end (in case we declared 'As Long').
When declared 'As String' in the return-value, then VB enforces freeing *always*, no
matter what (and has the small "off-by-one-char" bug).
Olaf
Last edited by Schmidt; Jan 13th, 2015 at 08:21 PM.
-
Jan 13th, 2015, 09:11 PM
#6
Re: problems with external lib calls
The Declaration as it is currently will force VB to make a freeing-attempt (unrelated to __stdcall-stack-issues) on the returned static string-pointer-allocation, and thus causing a crash.
That part summed it up quite nicely, thank you
-
Jan 13th, 2015, 10:10 PM
#7
Re: problems with external lib calls
Why not just turn it around and return the result into a provided buffer pointer parameter? Isn't that more typical anyway?
Then:
Code:
Public Declare Sub GetVersion Lib "mylib.dll" (ByVal lpBuffer As String)
Pad your String out before the call. VB6 assumes ANSI so it implictly handles Unicode/ANSI/Unicode conversion before and after the call.
The other way you get back a pointer, have to copy the data and convert to Unicode, and then worry about getting the buffer freed back in the DLL by some miracle.
-
Jan 13th, 2015, 10:15 PM
#8
Re: problems with external lib calls
Originally Posted by edmontreal
... but now it doesnt load ACTIVEXs files which are not registered with regedit, before with just copying the activex in the same folder as the exe file it had worked fine.
Just don't do this, it is a leading cause of DLL Hell.
Use a proper installer, the world will thank you.
-
Jan 14th, 2015, 09:56 AM
#9
Thread Starter
New Member
Re: problems with external lib calls
Thanks a lot for the answers related to the first problem. Now, the second problem is not solved because it happens even if i dont call the problematic function, it seems as a matter of the differences between a RELEASE exe and an interpreted execution as well the differences between the optimizations settings, so if somebody knows these details i think i would be able to know where to look for bugs , anyway i'll look for a similar problem in the others functions, just in case, Thanks again and i ll keep you updated.
-
Jan 14th, 2015, 01:28 PM
#10
Thread Starter
New Member
Re: problems with external lib calls
Both problems solved guys, the second was a difference between the libraries that the program reads when it was in the modified output folder and in the project folder, MY BAD people, but anyway when the compiler optimizations were removed the release didn't crash that's why i was lost, a very deceiving problem with a very simple cause. Now it works perfectly in debug, RELEASE, optimizations set or not.
Nevertheless i think that would be good if somebody could explain what exactly does the compiler when optimizations are set and why a program that uses an external library could crash if it use optimizations and run perfectly when not optimizations are set even with the wrong dll.
Again, thanks a lot. I was a little scared trying to give some new functionality to an old program in a language that i have never touched, but the experience wasn't bad at all, vb6 , 1998 !!!, , not bad at all except for two or three annoying behaviors of the IDE. The community rocks as well
-
Jan 14th, 2015, 02:24 PM
#11
Re: problems with external lib calls
Originally Posted by edmontreal
Both problems solved guys, the second was a difference between the libraries that the program reads when it was in the modified output folder and in the project folder, ...
In case you want to ensure the same Std-Dll (or Set of Std-Dlls) to be used in both modes:
IDE-Debug-Mode and Release/Binary-Mode - you can ensure that per Preloading of the Dll(s)
in question (per LoadLibrary-WinAPI)
VB6 App.Path will resolve (in IDE-Mode) to the Directory where your *.vbp is placed in -
and when running compiled, App.Path resolves to the Directory the compiled Binary in question
was placed in.
So, when you have a Project-Root-Folder with a *.vbp in it organized this way:
\MyProject\
... MyProject.vbp
... SomeForm.frm
... SomeClass.cls
... \Release\
...... MyProject.exe
...... \Bin\
......... MyStd.dll
......... MyOtherStd.dll
Then you can preload Dlls explicitely at an early point in your Project-Startup (usually Sub Main()):
Code:
Sub Main()
Dim DllPath As String
If App.LogMode Then 'we run as a compiled Binary
DllPath = App.Path & "\Bin\"
Else 'we run in the IDE
DllPath = App.Path & "\Release\Bin\"
End If
LoadLibrary DllPath & "MyStd.dll"
LoadLibrary DllPath & "MyOtherStd.dll"
End Sub
This way you can ensure that you'll always use the same version of Std-Dll(s) -
no matter if you run in the IDE or from the compiled Binary.
Originally Posted by edmontreal
...but anyway when the compiler optimizations were removed the release didn't crash that's why i was lost, a very deceiving problem with a very simple cause. Now it works perfectly in debug, RELEASE, optimizations set or not.
Nevertheless i think that would be good if somebody could explain what exactly does the compiler when optimizations are set and why a program that uses an external library could crash if it use optimizations and run perfectly when not optimizations are set even with the wrong dll.
Not sure which optimizations you mean - the largest difference in compilation-behaviour is,
when you switch between PCode-compiled Binaries and native-compilation.
If in native compilation-mode, there's intermediate C-Code generated - which is then compiled
by the MS-C(++)-Compiler Version 6 (C2.exe in the VB6-Program-Folder) - and here a few
more Optimizations are available - and if you checked the optimization "No Array-Bounds-Check"
for example - and your current VB-Code ecpects a 160Bytes-Byte-Array returned from your
C-Dll - and the older Dll-version delivered for example only a 128Byte long Array - then such
Crashes are easily explainable.
Since we don't have all the details of your project we can only speculate - but usually -
when I discovered discrepancies (no matter which ones) in Error-behaviour between different
compile-modes or optimization-settings, then it was in almost all cases my fault.
Originally Posted by edmontreal
I was a little scared trying to give some new functionality to an old program in a language that i have never touched, but the experience wasn't bad at all, vb6 , 1998 !!!, , not bad at all except for two or three annoying behaviors of the IDE.
Well, the vbRuntime and certain COMponents were maintained a few years longer than that...
And yeah - VB6 may serve as a good example, what Devs and Engineers really prefer (and can accomplish)
with certain APIs and ABIs which remain stable and unbroken over more than just a few years (warts and all)...
Olaf
Last edited by Schmidt; Jan 14th, 2015 at 02:28 PM.
-
Jan 15th, 2015, 10:51 AM
#12
Thread Starter
New Member
Re: problems with external lib calls
The optimizations that you can set if your option is "Compile to native code" which are "Optimize for fast code"-- default, "Optimize for small code", "No optimization", the question again was why with the option "Optimize for fast code" does not work and with "No optimization" works even with the wrong library version, of course, the problem was not VB , was me, but now im a little curious about these optimizations in the compiler
thanks again
-
Jan 15th, 2015, 11:34 AM
#13
Re: problems with external lib calls
Originally Posted by edmontreal
The optimizations that you can set if your option is "Compile to native code" which are "Optimize for fast code"-- default, "Optimize for small code", "No optimization", the question again was why with the option "Optimize for fast code" does not work and with "No optimization" works even with the wrong library version, of course, the problem was not VB , was me, but now im a little curious about these optimizations in the compiler
Never used the VB5/6 native-Compilation with anything else than "Optimize for fast code" (usually
accompanied by checking in a few of the additional Compile-Options to speed things up even further).
When I wanted a small Binary and speed was not really important, then I've always switched
directly to P-Code Binaries (P-Code compilation and speed is what you have, when running
a project in IDE-Mode - and if what you experienced there was sufficient, then there's no real
need to compile to a "fully native" Binary with the underlying C-Compiler).
That doesn't answer your question though - I perhaps just wanted to give an explanation upfront -
in case you will receive no satisfying answer here - since I can imagine, that among the native-Compile-
Options, the experience with: "No optimization" is IMO virtually non-existent among community-members
(for the reason stated above, that PCode-Binaries are the better "non-optimized" alternative).
Olaf
-
Jan 15th, 2015, 12:30 PM
#14
Thread Starter
New Member
Re: problems with external lib calls
Fair enough, just was curiosity, i was thinking about a irremediable vb6 bug when that was not the case. The lesson is that if something doesnt work with the default settings then something is wrong with you not the compiler ( At least to be humble from the beginning is a good practice even when every compiler is not 100% infallible, by the way, i had some crashes before restoring a wndproc that i actually solved doing tricks, i always blamed vb for that ). Thanks a lot!!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|