I'm working on a (rather horrible) project that involves importing a C++ class hierarchy through a dll interface. One of the more horrible details requires me know the 'decorated' names for the various class elements that are exposed - mostly member functions and static data.
There are many ways to achieve this - the assembly listing or map file, dumpbin, a dependency walker, the _FUNCDNAME_ macro, etc. Unfortunately, they all require me to actually compile the code or have the compiled dll - and all I have available is the header files. (That may leave you scratching your head for a minute - just take my word that it truly is a horrible project.)
Now, I can easily concoct something compilable from just the headers and use one of the above approaches. But if I can avoid it, that would be much better. So my question is: is there a way to browse decorated symbol names from within Visual Studio, a la Object Browser? I know that the decoration is technically done at compile time, but Intellisense does so many other things while you type that I'm hoping it might do this too.
If all else fail take that .h, rename it to .cpp, replace all semicolons (;) with
{
#pragma message(__FUNCDNAME__)
}
edit it a little, and compile it. You'll get your list.
Related
With the risk to fall into too specific question...
Given a C++ MFC (mixed, not shaked) project compiled with /CLR, I have 200 classes already defined.
When I add a new empty class to this project, an error raises when I compile and execute in debug mode.
An unhandled exception of type 'System.IO.FileLoadException' occurred
in Unknown Module.
Additional information: Could not load file or assembly 'ProjectA,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its
dependencies. Could not find or load a type. (Exception from HRESULT:
0x80131522)
ProjectA is the name of the MFC project itself. There is no reference to any ProjectA assembly on project configuration, and there is no reference to another custom assembly.
This project only have references to some .NET Framework assemblies, in order to allow that some of custom defined classes in the project can use CLR classes.
Then, the question is...
Do you know whether there is any limitation of class number on a MFC C++ project?
EDIT:
As I say in comments, in release mode the compilation succeed without errors.
Also, I clean, build, clean, close Visual Studio, reboot computer... and the problem still appears.
If I keep in 200 classes, there is no error. When I go to 201, the error appears.
Currently I'm trying to reproduce in a new default MFC project, adding classes till arrive to 200, to confirm that there is a real limitation.
EDIT 2: ERROR FIXED
Great. #MSX and #frymode show me how avoid the error with his comments.
In the Visual Studio development environment (source / source):
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling (/GF) property.
Thank you guys!
The /GF hack is a known workaround for this problem. It is however not a correct one, you are putting a band-aid on a heavily bleeding wound. Pretty important that you heal the problem instead of putting a patch on it, this heavily affects the way your program runs at runtime as well.
The problem maker is the <Module> class, an internal class that the C++/CLI compiler generates. You can see it with ildasm.exe or a good decompiler. This class is required as a home for declarations in your program that are not class members, valid in native C++ but not supported by the CLR. Which demands that every variable or function declaration is a member of a class. The C++/CLI compiler solves it by moving such a declaration into the <Module> class.
There is however a limit on the number of members in a class, they are represented in the metadata of the .NET assembly with a metadata token. An index into other tables. The upper byte identifies the table number, the lower bytes are the index in the table.
You exceeded that limit. This is bad.
A problem with the /clr compile option is that it works too well. It is capable of compiling any C++03 compliant native C++ code to MSIL. Such code will be just-in-time compiled to machine code by the jitter, just like normal managed code. It is however not verifiable code and it doesn't act like managed code at all, you can blow up your program with pointer fumbles just as easily. And above all, it is not code that's optimized with the native C++ back-end. Only the jitter optimizer has a shot at improving that code, it cannot do nearly the quality job that the native C++ optimizer can do, given that it runs with a hard upper limit on how much time it can spend on doing that job.
Have a look-see with a decompiler to see what ended up in that <Module> class. That's going to be overwheliming at first, you know you've got a big one right now. You fix this problem by spending more time segregating the code into the managed parts and the native parts. Where the native code should be compiled without /clr in effect. It is a per-source file setting, you can even switch back-and-forth in a single source code file with #pragma managed. The simplest way to segregate is by keeping your native code in its own library or DLL.
This link shows that there's no limit to the number of types you can have in a namespace (not a project). Considering, that a namespace can be split across different assemblies, you could, at least in theory, have an unlimited number of types. However, this post affirms that the maximum number of classes in a .DLL
is 16777215. Probably, you'll run out of memory before you reach that number of classes :)
Just for information: there seems to be a limit to the number of fields per class, though.
P.S.:
Here's the solution to your problem taken from this link
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling property.
Consider a C++ API defined as a series of __options(declexport/import) classes.
Further, assume that the caller is never permitted to call the ordinary operator new(size_t) on these classes. Either a static factory method does the new-ing or there is a class-specific operator new. And ditto marks on the delete size as needed (frequently just a virtual destructor).
Now, if you compile and link a DLL and an IMPLIB of with the tools from VS2010, can you hand that implib and DLL to a user of VS2005 and expect it to work?
MFC is not involved here at all.
I'd be particularly grateful to any reference to any relatively formal Microsoft statement on the subject.
So long as the name mangling on the C++ API is identical (they are), and does not use STL-type specific parameters, such as basic_string or std::map, whose implementation may have changed between releases of the compiler (and they have), then it should just work.
Of course, you'll want to make sure you either compiled your DLL using /MT mode (static linked runtimes), or include the redistributables for VS2010 runtimes with your supplied libraries and link targets.
EDIT: Expanding on "don't pass in types that have version-specific implementations". A partial list is most easily found by looking at the output of the exports of MSVC100P.DLL.
cd %VS100COMNTOOLS%\..\VC\redist\x86\Microsoft.VC100.CRT
DUMPBIN /exports MSVCP100.DLL
The next issue will be header-only implementations of things like map or set which have changed under the hood between versions of the compiler.
This is why it's highly recommended that only scalar types be passed across boundaries between memory arenas. And thus, simple tests will pass, and be reliable.
You have not mentioned if you have used MFC to create the DLL's .If you have, regular DLL's should work , but I dont think extension shall work as the latter links to the MFC dlls .I am including links for your reference.
http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c4017
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/Q_20385543.html
http://msdn.microsoft.com/en-us/library/26h8x9sy%28v=VS.100%29.aspx
EDIT
If its a normal DLL, there should not be any problem.Also depends on the linkage type.
Visual Studio seems to want to put class contructor code and event handling code in the .h file. I have only been involved in small 1 man projects and was wondering what the general industry standard was.
For Visual C++ Application projects what code would one put in the .h file? I am used to the mode classical C++ way of declaring your class in the .h file and coding in the .cpp file. Does this still apply to Visual Studio applications?
I have a strong C background which would explain my preference for this. The VSC++ compiler doesn't seem to mind.
In short: What is one supposed to put in which type of file?
TIA
Ends
There is no widely accepted industry standard. By putting (short) function definitions in the header, you give the compiler a better chance to inline the code. The benefit is that it can make the code run faster (keep those functions short, though). However, this comes at the cost of exposing more code to the clients who include that header, making you (or your colleagues) recompile more files when you change the implementation.
You also have to take into account the cost of going against your tools. Since VC++'s wizards insist on putting the functions in the headers, you have to move them everytime if you disagree.
It's really project-specific, I would say.
If you're using MFC and you're talking about the generated code, it's best to leave it alone.
If you're trying to do 'normal' C++ development, put as little as you can get away with in the header, as it means client code doesn't depend on too many implementation details. What you can get away with depends a little on use of templates, and how much indirection your performance budget can support.
For Visual C++ Application projects
what code would one put in the .h
file? I am used to the mode classical
C++ way of declaring your class in the
.h file and coding in the .cpp file.
Does this still apply to Visual Studio
applications?
Short: Yes
Long: Depends on the person or language. In c++ the header is for declaring and cpp for the coding. For C# you have one file (or if you use interfaces, 2)
This might seem minor, but just remember: headers are #included in several places. (And headers including headers complicates things further.) Any time you change a header, a lot of files are gonna be compiled again. Keeping as little of frequently changing code in the header reduces recompilation of dependant files.
Another thing: an uncluttered header file gives you a quick overview of what a class/form has to offer.
Whats the easiest way to find out what programming language an application was written in?
I would like to know if its vb or c++ or delphi or .net etc from the program exe file.
Try PEiD
of course if they used a packer, some unpacking will need to be done first :)
Start it up and check what run-time DLLs it uses with Process Explorer.
If that doesn't make it immediately obvious, search the web for references to those DLLs.
Most disassemblers (including Olly I think) can easily show you the text contained in an EXE or DLL, and that can also sometimes give a clue. Delphi types are often prefixed with T as in TMyClass.
If it's a small executable with no DLL references and no text you might be SOL. At that point you'd need to look for idioms of particular compilers, and it would be mostly guesswork.
There is an art to detecting what language a program was written in. It is possible but there are no hard and fast rules. It takes a lot of experience (and it also leads to the question "Why would you want to..." but here are a few ideas on how to go about it.
What you're looking for is a "signature". The signature could be a certain string that is included by the compiler, a reference to an API that is quite common in the programming tool being used, or even a style of programing that is common to the tools being used, visible in the strings contained in the application.
In addition, there are styles to how an application is deployed: various configuration files found in the deployment directory, dlls and assemblies and even images, directories or icons.
Java applications wrapped in a self-launching executable will contain references to java libs, and will likely have certain libraries or files included in the same directory that indicate that it's java.
As indicated in other answers a managed assembly will show certain signs as well: you can open it in Reflector etc. While it is correct that c# and VB are "interchangable" once compiled, it is not true that they are identical. If you use Reflector to disassemble VB code you will quite often see that the assembly references the Microsoft.VisualBasic.dll assembly. You'll be able to tell the difference between Mono applications because they will most likely contain references to the mono assemblies.
Many compilers assemble and link code in certain ways, and leave footprints behind. For example, examining a window executable using "strings: tab in Process Explorer, you'll see a lot of strings. Using these you may be able to determine programming styles, methods called, error or trace methods withint the exe.
An example is that compilers use different mechanisms for localization: Microsoft stores localized strings in XML files or resource files. Other compilers will use a different tactic.
Another example is c++ name mangling. The CodeWarrior compiler uses a different algorithm to mangle the names of the member variables and functions of a call than Visual Studio.
I suppose you could write a book on the subject of accurately determining the lineage of any executable. This subject would probably be called "programming archeology".
You could try using Depends to see what runtime dependancies it has, which might give some clues.
The easiest way is to ask the developer of the program. It does not require any knowledge and utility programs.
Determine Delphi Application
Use eda_preview270.exe (from here) or some other spy tool and check the window class names. If they read like TButton or TfrmBlubb, it's a VCL app. If there is an "Afx" in them, it's probably MFC.
Compiled languages (by this I mean no scripting languages, or Java, .NET, etc.) are compiled into CPU assembly instructions, which is essentially a one-way conversion. It is not usually possible to determine which language a program was written in. However, using a dependency walker, you could potentially determine which runtime library the program was loading (if any) and therefore determine which language it used (e.g. MS Visual C++ 9 uses msvcr90.dll).
you can check is that a .net assembly or not by trying to open with ildasm.exe tool
PE Detective works best for me.
In general, you can't.
If you can load it into Reflector, you know it is a managed assembly.
That's a good question. There isn't any general way to tell, but I bet most compilers and libraries leave a mark in the resulting EXE file. If you wanted to spend a lot of time on it, you could gather a bunch of EXEs written in known languages and scan for common strings. I would image you'd find some.
Dependancy Walker, which someone else mentioned would be a good way to look for telltale dependencies, like versions of MSVCRT, etc
i'd try running the .exe thru a 'strings' program to get assorted hints.
If I remember correctly PE Explorer Disassembler gives some information about compiler that creates given not .net and java binary, for .net use Reflector or ILDAsm tool
The easiest way that I found (at least in computer games) was to look in the "redist" folder nested within the game's main folder. It might be obvious to some of you that are more experienced in programming yourself, but the specific purpose of the MSI in this folder is to allow the setup.exe file to automatically install the prerequisites for the game itself.
For example:
In Empire Total War, there is an MSI called "vcredist_x86-sp1.exe". This indicates that the game/program was written in Microsoft's "Visual C 2005" in the .NET Framework (usually).
In fact, if you open the MSI/EXE, the installer should immediately indicate the language it's written in and which version.
The reason I'm familiar is because I code in C# and VB in the .NET Framework and we auto-install the prerequisites for our business app.
Hope this helps!
This I think is related to my use of the nlog C++ API (and my question on the nlog forum is here); the purpose of my asking this question here is to get a wider audience to my problem and perhaps to also get some more general ideas behind the VB6 IDE's failure to build in my particular scenario.
Briefly, the problem that I am having is that I am having trouble building VB6 components which reference unmanaged C++ components which have calls to nlog's C\C++ API (which is defined in NLogC.DLL). The build problems are not occurring during compile time, they are occurring when the binary is being built which suggests to me that it's some kind of linker type problem? Don't know enough about how VB6 binaries are produced to tell. The VB6 binary is produced, but it is corrupted and crashes shortly after it is invoked.
Has anyone had any similar experiences with VB6 (doesn't have to be related to nlog or C++)?
edit: Thanks for all the responses to this rather obscure problem. Still no headway unfortunately; my findings since I posted this:
'Tweaking' the compile options doesn't appear to help in this problem.
Adding a reference to the nlog-enabled C++ component from a 'blank' VB6 project doesn't crash it or cause weird build problems. So it isn't a 'native' VB6 issue, possibly an issue with the interaction between nlog and the various components and 3rd party libraries used by other referenced components?
As for C++ calling conventions: the nlog-enabled C++ component is - as far as I can see - compliant to these conventions and indeed works fine when referenced by VB6 as long as it is not making any nlog API calls. Not sure if the nlogc.DLL itself is VB6 compliant but I would have thought that that is immaterial since the API calls are being made from the C++ component; VB6 shouldn't know or care about what the C++ component is referencing (that's as far as my understanding on this goes...)
edit2: I should also note that the error message obtained during build is: "Errors during load. Please refer to "xxx" for details". When I bring up the log file, all that there is in there is: "Cannot load control xxx". Interestingly, all references to that particular control disappears from that particular project resulting in compile errors if I were to try to build again.
Got around the problem by using NLog's COM interface (NLog.ComInterop.DLL) from my unmanaged C++ code. Not as easy to do as the C\C++ API but at least it doesn't crash my VB6 components.
I would try tweaking some of the Compile options found in the Project, Properties menu, Compile panel to see if they yield any additional hints as to what is going wrong.
For example if you compile the executable to p-code rather than native code does it still crash on startup.
What error message do you get when you run your compiled binary?
I doubt the compiler/linker is the problem: project references in a VB6 project are not linked into the final executable. A project reference in VB6 is actually a reference to a COM type library (which may or may not be embedded in a .dll or other binary file type). Project references primarily serve two purposes:
The IDE extracts type information from the referenced type libraries which it then displays in the Object Browser (and in the Intellisense drop-down)
At compile-time, the compiler extracts the type information stored in the referenced libraries, including the CLSID of each class that you instantiate, and embeds this data into the executable. This allows your executable to create instances of classes contained in the libraries that you referenced.
Note that the compiled binary doesn't link to any code in the referenced libraries, and it doesn't even contain the filenames of the referenced libraries. The final executable only contains the CLSID's and other type information that it needs to instantiate COM objects at run-time.
It is much more likely that the issue is with NLog, or with how you are calling it from your code, rather than something gone awry in the VB6 compile process.
If you think it might be a linker problem, this should crash it the same way:
create a new standard project (of any kind)
add a new module and copy the "declare"-statements into it
compile
If it doesn't crash it is something else.
It would help an exact description of the error or a screenshot of what going on.
One thing to check is wherever NLogC.DLL or the C++ DLL you built have the correct calling convention defined. Basically you can't have the DLL function names mangled or use anything but the STDCALL calling convention. If the C++ DLL has not been created with those two things in mind then it will fail to work with VB6.
MSDN Article on Calling convention.
"Cannot load control xxx" errors can be caused by .oca files which were created from a different version of an .ocx than currently used. If that is the case, deleting the .oca files helps.