as mentioned here:
http://www.powerbasic.com/support/forums/Forum4/HTML/012129.html
I am having great difficulty with XPsp3 and VS2008.
dumpbin is giving me the error:
Microsoft (R) COFF Binary File Dumper Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file C:\sqlite3.dll
File Type: DLL
C:\sqlite3.dll : fatal error LNK1106: invalid file or disk full: cannot seek to 0x6179a
When I look for 'queryopen' events in procmon I get NAME NOT FOUND errors for:
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\link.exe.Local
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\dumpbin.exe.Local
(plus a few for manifest files)
Any idea how I can get dumpbin to work?
Mike,
Where did you get the file -> sqlite3.dll. Its not in my windows version.
It's obviously a component of SQLite !!!!
http://www.sqlite.org/download.html
Hi Hutch,
Its just a renamed dll file. I have some legacy code to maintain that uses SQLite.dll (version2 I think) so to avoid accidents I renamed it.
I created a simple dll with P B called AddShow.dll. It can be found here:
http://www.transferbigfiles.com/Get.aspx?id=7d86fa0b-6ddc-4f6f-8d31-2c20824aae9a
along with the VC2008 project.
The task is to link it statically with a .LIB file in VS2008. This has thus far defeated everyone!
The main problem is that dumpbin will not run because it is trying to open dumpbin.exe.local. What on earth is that?
Hi MikeT,
If you have an import library, you can convert it to a def file with MS COFF import library to module definition file converter (http://vortex.masmcode.com/files/lib2def21.zip)
Thanks for that tool,
Actually this is the first step in creating a .LIB file. I should have made that clear.
The approach is summed up here:
http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/
I have a Dll and a header file. THATs IT.
now I need to export the functions using dumpbin which I just cannot get to run.
Have you tried the /DISASM option? This may be stupid but, do you know what the options that are available?
Paul
you mean the addshow.dll?
why are all the timestamps messed up showing 1969 and 1970?
addshow.dll (hex) (dec)
.........
Portable Executable starts at 80
Signature 00004550 (PE)
Machine 014C (Intel 386)
Sections 0004
Time Date Stamp 00003039 Wed Dec 31 22:25:45 1969
......................
....................
Exp Addr Hint Ord Export Name by AddShow.dll - Sat Feb 7 03:47:36 1970
-------- ---- ----- ---------------------------------------------------------
00001E9C 0 1 AddTwoNum
00001E35 1 2 LIBMAIN
00001F26 2 3 ShowString
Mike,
Is there some reason that you can't use the def file that is included with the DLL?
See sqlitedll-3_6_18.zip here (http://www.sqlite.org/download.html).
you mean the addshow.dll?
YES!
now why can't I do that?
>why are all the timestamps messed up showing 1969 and 1970?
because its made by powerbasic perhaps?
>Is there some reason that you can't use the def file that is included with the DLL?
There is no Def file with this dll. I'm really sorry I mentioned SQLite becuase it has only confused things. I am just trying to convert PB dll's with no .Def or .Lib files.
Do you realize that PowerBasic's DLLs are proprietory and what you are trying to do is illegal?
Paul
Mike,
I saw where you mentioned another DLL, but I dismissed it because it did not seem likely that you would need to automate the creation of a def file for a "simple DLL", where I interpreted simple to mean that it exported only a small number of functions.
This def file was created by pexports.exe from the MinGW\bin directory:
LIBRARY AddShow.dll
EXPORTS
AddTwoNum
LIBMAIN
ShowString
>Do you realize that PowerBasic's DLLs are proprietory...
Huh? Are you working on the assumption that I am trying to decompile powerbasic compiler Dll's perhaps?
Please re-read the thread.
I have *CREATED* a Dll (AddShow.Dll) in this case, using the PB compiler (that I own).
The concept is to move (run) away from powerbasic and call my legacy PB code from C++ in this case as Dll's.
So to recap, its my Dll, made from my code, with my copy of the compiler.
Michael
oooh what is pexports.exe?
http://www.emmestech.com/moron_guides/moron1.html
When i use:
AddShow.DLL | sed 's/^_//'
I get:
C:\C++Projects\pexports.exe: 's/^_//': could not load PE image
Added:
I just installed MASM and ran dumpbin in the bin folder:
/EXPORTS AddShow.dll
It worked!
Microsoft (R) COFF Binary File Dumper Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file AddShow.dll
File Type: DLL
Section contains the following exports for AddShow.dll
0 characteristics
314328 time date stamp Sat Feb 07 00:47:36 1970
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint RVA name
1 0 00001E9C AddTwoNum
2 1 00001E35 LIBMAIN
3 2 00001F26 ShowString
Summary
1000 .data
1000 .link
1000 .rloc
2000 .text
No idea why the dates are off....
So why wont it work in the VS2008 bin folder?
Mike,
If I have it right you want to use a DLL you wrote in PowerBASIC in a C++ program that normally requires an import library to link it statically to the EXE file ? For those not familliar with PowerBASIC, it creates DLLs without any import libraries or DEF files.
Basicaly you need to write C++ prototypes for the DLL functions you EXPORT making sure that you use the correct calling convention which in this case is simple, PowerBASIC by default uses STDCALL, and make sure the names you EXPORT are prototyped in a case sensitive manner and C/C++ requires this.
I know how to do this in MASM but there may be tools that don't require that you learn enough MASM to create the library you need.
>If I have it right
yes.
>PowerBASIC by default uses STDCALL
yup. But I can also declare them as CDECL if need be
>make sure the names you EXPORT are prototyped in a case sensitive manner
yes
>C++ prototypes for the DLL functions
no problem
The issue for static linking is creating the .LIB file. Following this method:
http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/
I need to make the .Def file first with dumpbin (so far 3 days work finally requiring the install of MASM!
unless I am missing something, this is the only way.
For Dynamic linking, I can call LoadLibrary() and GetProcAddr() then call the functions with a pointer of course but I don't want to do that in this case.
If you know the name of the dll and the functions, can't you just type out a def file? It's only a text file.
That would probly be the easiest way.
Hi MikeT,
I downloaded sqlite3.dll from the link posted by MichaelW. Attached is sqlite3.def extracted from this dll.
Vortex,
Im sorry, the SQLite dll was a bad choice. I am not trying to make a .lib for that library. I just mentioned it as an example of a dll that one might want to use because it was used in the example here:
http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/
The test dll I AM trying to link statically is called AddTwoNum.dll. Sorry for the confusion
sinsi,
Yes I just realized that! urgh.
I finally got the VS2008 dumpbin to work by copying the following files to a seperate folder
dumpbin.exe
link.exe
lib.exe
mspdb80.dll
If you copy mspdb80.dll to the bin folder of VC then the compiler will say:
"c1902 program database manager mismatch please check your installation"
so the files have to be combined in a seperate folder
Now the problem is the calling convemtion
http://support.microsoft.com/kb/131313
"Specifically, the functions need to have been declared to use the C calling convention."
I could simply add CDECL to every PB function that I have ever written, but thats a pain. They are all STDCALL so I would like to use them that way.
Now I need to create a .Lib file using the stdcall convention.
http://www.geocities.com/yongweiwu/stdcall.htm
writing the def file like this;
EXPORTS
__stdcallAddTwoNum
__stdcallLIBMAIN
__stdcallShowString
This creates a .lib file but when I try to compile my VS2008 C++ project I get the linking error:
main.obj : error LNK2019: unresolved external symbol _AddTwoNum@12 referenced in function _main
C:\C++Projects\UseWrapDll\Debug\UseWrapDll.exe : fatal error LNK1120: 1 unresolved externals
somehow it is looking for a decorated function name now
Hi MikeT,
Creating an import library with decorated function names is easy. You have the functions below :
AddTwoNum
LIBMAIN
ShowString
Now, the question is how many parameter takes each function. For example, ExitProcess takes one parameter :
1 parameter * 4 bytes per param = 4 => _ExitProcess@4 ( This is the decorated form. )
MessageBoxA takes four parameters :
4 parameters * 4 bytes per param = 16 => _MessageBoxA@16
AllocConsole : no any parameters :
0 parameter * 4 bytes per param = 0 => _AllocConsole@0
You can create import libraries with Polib coming with the Masm32 installation.
Well isnt that handled by the function declaration in my cpp file?
extern "C" { // put Dll C function prototypes here
int __stdcall AddTwoNum(int n, double f); // __stdcall
}
Hi MikeT,
You are right. Please could you post here the declaration of the other functions?
Hi MikeT,
I could not find the source code of AddShow.dll in the zip file you posted here (http://www.transferbigfiles.com/Get.aspx?id=7d86fa0b-6ddc-4f6f-8d31-2c20824aae9a)
Analyzing AddShow.dll, I found that :
AddTwoNum takes 3 parameters
ShowString : 4
and LIBMAIN takes 3 parameters.
Here is the module definition file :
LIBRARY AddShow
EXPORTS
"_AddTwoNum@12"
"_LIBMAIN@12"
"_ShowString@16"
Now, you can create an import library with decorated names :
polib /OUT:AddShow.lib /DEF:AddShow.def /MACHINE:IX86
or
def2lib.exe AddShow.def
In both cases, you should get a library of 1786 bytes. ( Tested with polib V6.00.1 and def2lib V1.1 )
Sorry I didn't think of that. Typically I will have at least a header file with the function definitions in it
Here is the AddShow.Dll code:
' A Dll to test C++ linking
#COMPILE DLL "AddShow.dll"
#INCLUDE "WIN32API.INC"
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION LIBMAIN SDECL ( BYVAL hInstance AS LONG, _ ' main
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG ) EXPORT AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
LIBMAIN = 1 ' DLL Attached successfully
CASE %DLL_PROCESS_DETACH '
END SELECT
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION AddTwoNum SDECL ALIAS "AddTwoNum" ( BYVAL k AS LONG , _
BYVAL mpg AS DOUBLE ) EXPORT AS LONG
MSGBOX "k="+STR$(k) + ", mpg="+STR$(mpg),64,"DLL Values Received:"
FUNCTION = k + CLNG(mpg)
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION ShowString SDECL ALIAS "ShowString" ( BYVAL k AS LONG , _
BYVAL mpg AS DOUBLE , _
BYVAL sPtr AS DWORD ) EXPORT AS LONG
LOCAL pzStr AS ASCIIZ PTR
pzStr = sPtr
MSGBOX ">"+ @pzStr +"<",64,"DLL Display String of Len:" + STR$(LEN(@pzStr))
FUNCTION = LEN(@pzStr)
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
How did you create the .Def function names? (I need to automate that)
Why are decorated names required with stcall and not cdecl?
Hi Mike,
I can see where I reached the wrong conclusion. Sorry for my comment.
Paul
No problem Paul. No offence taken.
Vortex, I suspect we are in different time zones (are you in Europe maybe?)
I ran polink with the switches you specified:
/OUT:AddShow.lib /DEF:AddShow.def /MACHINE:IX86
And I get:
POLINK: warning: No object files specified; libraries used.
POLINK: error: Unresolved external symbol '__AddTwoNum@12'.
POLINK: error: Unresolved external symbol '__LIBMAIN@12'.
POLINK: error: Unresolved external symbol '__ShowString@16'.
POLINK: error: Unresolved external symbol '___DllMainCRTStartup@12'.
POLINK: fatal error: 4 unresolved external(s).
(I have v5.00 of polink installed with MASM yesterday)
I am guessing because the function names in the dll are not decorated?
where do you download polink v6?
Hi MikeT,
I am on GMT + 3:00
I built the import library with polib Version 6.00.1 I copied this latest version to my \masm32\bin folder. My apologies, I should tell it you before.
You receive error messages because there are some extra underscore characters in your import library. For example, instead of __AddTwoNum@12, you should have _AddTwoNum@12 in your library ( only one leading underscore )
The function names in the DLL should not be decorated here.
You can get the latest Pelles tools from :
http://www.smorgasbordet.com/pellesc/download.htm
I created manually the def file. I understand that you need to automate this task. Does the Power Basic compiler create an object file for the DLL? It's possible to convert MS COFF object modules to def files.
Attached is the import library created with polib V6.00.1
Success!
Thank you for all this help! This is a minefield!!
Does the Power Basic compiler create an object file for the DLL?
ha ha ha... powerbasic can't even get the date right it seems.
I downloaded and installed Pelle's C to get polib. I think his work is great. What an amazing contribution. Hutch too.
I explored Pelle's C for while a couple of years ago but the reality is I need OOP classes to work on team projects in industry.
polib now works as you describe
>The function names in the DLL should not be decorated here.
right
>I created manually the def file
So I need to code this procedure because I have MANY Dlls to convert and I want to automate this whole process. If I am following the subtext correctly, I *must* use decorated names if I use the stdcall calling convention yes?
In which case, is there any code that I can use (written in any language) that creates decorated names?
Within my experience not all STDCALL DLLs use decorated names. A quick way to determine what sort of names a DLL, library, or object module contains is to open the file in an editor and take a look. Most of what you see will be gibberish, but the names should be readable.
Edit: "Use" is the wrong word, that should have been:
Within my experience not all STDCALL DLLs contain decorated names (and now that I check, most don't).
And if the target DLL does not, then I can't see any way to fully automate the creation of an import library.
Well this is where I remain confused. My Dll does not use decorated names yet the project that calls it will only link if decorated names are used.
I am guessing this is a condition C++ imposes?
Hutch, I see you dealt with this question in 2005
http://www.powerbasic.com/support/forums/Forum4/HTML/012129.html
Vortex, how did you know how to decorate the names
"_AddTwoNum@12"
"_LIBMAIN@12"
"_ShowString@16"
why not
"_AddTwoNum@1"
"_LIBMAIN@2"
"_ShowString@3"
(using the ordinal from dumpbin)
for example?
Mike,
The trailing number is the bytecount for the arguments passed to the function. When you see,
_MessageBoxA@16
It has 16 bytes of arguments. This info is for the linker to check the arguments.
Aaaah so its not decoration at all then. Great!
So if I have four arguments that are 4Byte LONG integers for example the byte count would be 16.
If I have four 8Byte DOUBLE's then the byte count would be 32 correct?
So I can write a program to automate this after all.
All I need is a way to list the arguments of the functions from the Dll itself.
dumpbin options
http://support.microsoft.com/kb/177429
don't seem to cover this.
There must be a way do it and get the byte count. Possibly from the PE header perhaps?
If not I will have to go through every exported function and count the bytes by hand. Urgh I hope not. I think I would rather use the CDECL calling convention.
How many additional clock cycles is the CDECL function call over the STDCALL?
Hi MikeT,
You are right with the byte calculation. I already explained it here (http://www.masm32.com/board/index.php?topic=12481.msg96074#msg96074)
It's possible to write a tool creating def files from Power Basic source code files. I am not a PB user but I see that the symbol ' means comment.
' ##AddTwoNum=12
A tool scanning the PB source code should interpret the line above like the following :
- A line with the leading ' symbol is a commented line
- The double # symbols means that the following word ( here AddTwoNumb ) should be copied to the destination def file.
- Finally =12 should be translated as @12
The output :
"_AddTwoNum@12"
Naturaly, you can find better methods to extract def files from PB code. My proposal above is a simple example.
A more advanced tool can convert the following code :
FUNCTION AddTwoNum SDECL ALIAS "AddTwoNum" ( BYVAL k AS LONG , _
BYVAL mpg AS DOUBLE ) EXPORT AS LONG
MSGBOX "k="+STR$(k) + ", mpg="+STR$(mpg),64,"DLL Values Received:"
FUNCTION = k + CLNG(mpg)
END FUNCTION
to the simple entry :
"_AddTwoNum@12"
Oh now I feel like an idiot. I thought that explanation was describing decoration because I had it in my head that the @ sign indicated decoration. In the last 10mins I have finally understood this is the number of bytes for the stack and forgot your detailed explanation. Thank you for your patience. This is clearly a case of not being able to see the wood for the trees.
I think I have a PB code parser fro another tool I wrote years ago that finds un-used variables and deletes them in source code. I am sure it could be adjusted to serve. Thank you again.
Mike,
I have heard of the dumpbin method but years ago it was not very good and there are far better ways of doing it. Vortex has explained what is probably the best way to do this with Pelle's tools. For what its worth you don't have to have the trailing byte count to make a library. Also note that it is not optional to change the calling convention unless you feel like rewriting all of your PowerBASIC source code to C and getting it to work properly.
>you don't have to have the trailing byte count to make a library.
If its CDECL you are correct. But if its STDCALL you do need the byte count or the VS2008 linker will choke. Thats the rub.
>it is not optional to change the calling convention unless you feel like rewriting all of your PowerBASIC source code
Well I could simply insert CDECL before the function definitions in my PB code and then re-compile the DLLs.
The problem with that is that the C calling convention executes code that performs stack cleanup etc each tiem the function is called (STDCALL does not, hence the need for the byte count I assume)
I am wondering what the overhead for that is in Clocks?
Its the other way around, STDCALL balances the stack but is limited to fixed and known argument count, C can use variable argument count but the CALLER must balance the stack. I suggest you will have to use tools from the after market to make the libraries you want, its easy to do in MASM but you have to know how to use MASM It builds its own libraries on installation so its no big deal.
For the C calling convention the stack cleanup is just an:
add esp, N
So the overhead is minimal, and there is at least a possibility that eliminating the constant operand (that specifies the number of bytes to release) from the RET instruction would speed it up enough to compensate.
Hmmm that's not what I read here:
http://books.google.com/books?id=4VOKcEAPPO0C&pg=PA134&lpg=PA134&dq=cdecl+fastest+convention&source=bl&ots=WC3pL5wv5X&sig=Mr5ijgMgXFm5kohI9uSQpKMwBA0&hl=en&ei=15zRSuuiBJDgtgOC8f3vCw&sa=X&oi=book_result&ct=result&resnum=3&ved=0CBEQ6AEwAg#v=onepage&q=cdecl%20fastest%20convention&f=false
http://www.tantalon.com/pete/cppopt/compiler.htm
I am not worried about this tho:
"Having the caller being responsible for cleanup the stack gives slightly bigger programs since the stack maintenance code is now at many places whereas it"
http://www.ng-sw.de/mg-wikka/CallingConventions
But I trust you ASm guys more of course for obvious reasons. If you say CDECL is faster than STDCALL then I will simply compile all my Dlls using that calling convention and make a simple parser to create the .def file. Thats easier anyway.
Don't worry about the speed difference of different calling conventions ... it's negligible for normal purposes.
In my test, running on a P3, the C calling convention is slightly faster, but 3 cycles in 30 calls is a less than negligible difference.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
.686
include \masm32\macros\timers.asm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
ProcStdcall proc arg1:DWORD, arg2:DWORD
ret
ProcStdcall endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
ProcC proc C arg1:DWORD, arg2:DWORD
ret
ProcC endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke Sleep, 4000
counter_begin 1000, HIGH_PRIORITY_CLASS
REPEAT 30
invoke ProcStdcall, 1, 2
ENDM
counter_end
print ustr$(eax)," cycles, STDCALL",13,10
counter_begin 1000, HIGH_PRIORITY_CLASS
REPEAT 30
invoke ProcC, 1, 2
ENDM
counter_end
print ustr$(eax)," cycles, CDECL",13,10,13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
294 cycles, STDCALL
291 cycles, CDECL
Perfect!
That settles that then. I'll just use CDECL convention for all my PB Dll's.
This has completed a weeks work! Thank you all. I began last Saturday in an attempt to do a demonstration of the FastCGI library
http://www.coastrd.com/cheader
in C++ but ran into all these issues in VS2008 C++ compiler/linker.
The stdcall example has illuminated why cdecl is a more universal format.
Here are the results on my quad.
179 cycles, STDCALL
187 cycles, CDECL
Press any key to exit...
The amount of messing around to convert PB code to C convention is a waste of effort unless you have time to waste. There is effectively no performace difference for anything except the shortest of procedures.
Well I have to refactor my PB dll code either by figuring put the byte count when calling stdcall, or by inserting one word "CDECL" in the function declaration. Since the subsequent steps can be automated if I use CDECL I might as well make my like easy and go that route. Also the chance of making a mistake if I try to hand code many functions in the .def file is quite high.
http://www.winasm.net/forum/index.php?showtopic=97
"I used sometimes wsprintf without any type of stack-cleaning (as i saw in many examples) and the function works correctly"
Didnt know that.
Mike,
a DEF file looks like this, I think you have got the wrong idea of how its done.
LIBRARY tstdll
EXPORTS TestProc
The "LIBRARY" statement is for the name of the DLL, the EXPORTS statement is for the function name(s)
You would write the DEF file for your DLLs something like this.
LIBRARY MikesDLL
EXPORTS function1
EXPORTS MyNextFunction
EXPORTS AnotherFunction
etc ....
.