tags:

views:

211

answers:

5

I don't know much about dlls. I'm reading a book on COM. In which author is referring to something Exporting a function from a DLL. He tells how to do that but he doesn't tell what is it or why it should be done?

The method he suggests is: a) mark function with extern "C" (don't know why?) b) create a DEF file and add the function names in EXPORTS section of this DEF file. again no clue about why and what exactly is happening there?

Another thing that I don't understand is term symbols/symbol table.

  1. What does Exporting a function from a DLL mean?
  2. What is symbols/symbol table?

I would be thankful if any one can explain me in simple , clear & detail terms. Any web links or tutorials are also highly welcomed.

EDIT:

I've used DLLs in .NET. In which I just include using namespace line and add the dlls to references and they work.This is the only way I know how to use dlls. I don't know how using dll's in .net is different from using them in COM. Can any one relate the .NET too?

+1  A: 

Every .dll file has a service area storing the names of exported functions and the addresses of their implementations - this is called the symbols table. When a consuming application wants to call a function from a .dll file it calls LoadLibrary() and then GetProcAddress() to locate the address of the function. The symbols table is used to facilitate tghis lookup. If a function is not in that table GetProcAddress() will not find it and the consuming application will be unable to call it.

sharptooth
+2  A: 

Exporting a function from a DLL simply means that the consumers of the DLL will be able to call this function.

Conceptually it is similar to adding the function to an "interface" exposed by the DLL.

The symbol table is a table containing these export functions their Name, ID, and address.

Try this: http://msdn.microsoft.com/en-us/library/z4zxe9k8(VS.80).aspx

koltun
+1  A: 
  1. A DLL is, to a first approximation, a collection of functions that do interesting things. Some of those functions are intended for the user of the DLL, others are used internally by other functions, and the author doesn't intend for the DLL's user to access. After deciding which functions inside your DLL ought to be seen by the DLL's users, you make them visible by exporting them.
  2. Symbols are the names given to functions and other blobs of stuff inside a binary (DLL, EXE, etc.). Symbol tables are data structures inside binaries that store collections of these names, and provide linkers and other tools with a mapping from the name to the named blob.

You can see exported functions either with the dumpbin utility that comes with VS, or (much easier) via the depends.exe tool, which you can download here.

Marcelo Cantos
In .NET, a class is compiled to DLL(if we pass appropriate parameters to compiler). All the private members are invisible and public members are accessible right? Isn't that the case here in C++? private members invisible and public members accessible to DLL user.Also I edited my post. please check once.
claws
No, .Net assemblies are bound up in DLL's (and EXE's), but they are quite different beasts from traditional DLL's. The metadata exposed at the DLL level and at the Assembly are completely unrelated to each other; as a general rule, I don't think assemblies export any symbols as DLL export.sIn C++, as with C, symbols are only DLL-exported when you say so, either with a .def file, or by marking exported functions (including member functions) as __declspec(dllexport).
Marcelo Cantos
+2  A: 

DLLs in .NET are quite different to native DLLs. .NET DLLs contain bytecode, called CIL, which has enough information for other programs - such as the csc compiler - to work out the classes, types, interfaces etc that are contained within.

This is quite different to native DLLs. Native DLLs contain binary instructions & mostly unstructured data, and there is (in general) no way to work out what the data means - for example somewhere in the DLL may be the two bytes (in hex) 43 23 and there's no way to tell whether the program will interpret these as the characters C# or as the integer 17187 or a memory address, or even an instruction to feed to the CPU.

So, moving on to your questions:

  1. The symbol table is a piece of metadata for the DLL; it tells the compiler/linker how to convert void myDllFunc (int bar) into an address in the DLL. It's basically a look-up table. Exporting functions from the DLL is how you tell which functions you'd like to end up in that look up table - these are the functions that other code will be able to call, because it will be able to find them. Remember - without other information, there's no way to tell where myDllFunc starts.
  2. extern C is recommended because of the process of name resolution, and in particular, how C++ handles function overloading. When you have two functions:
int square (int x);
double square (double x);

the compiler needs some way to distinguish between them - the name "square" is now ambiguous, and can't be resolved to a single code address. C++ handles this by name mangling - the compiler takes the name of your function, square, and then adds some magic strings corresponding to the types in the function signature. So, for example, the compiler could see your two functions as:

int int+square+int (int x);
double dbl+square+dbl (double x);

and they're now no longer ambiguous (real compilers don't use such a simple scheme). There are now two problems here:

  1. You want to refer to that function as "square", not "int+square+int", and, worse,
  2. Different C++ compilers use different name-mangling rules.

In order to make it easier to interoperate, people generally mark functions they export with extern C, which makes the compiler use C's naming rules, in which the function's name is not mangled.

Edit to address comments: Declaring the function signatures extern C resolves the name mangling problem because C doesn't have name mangling. C can get away without name mangling because declaring two functions

int square (int x);
double square (double x);

is an error; the compiler/linker doesn't have to - and won't - handle that ambiguity.

Exporting a function from a DLL is nothing more than adding the function to the symbol table. This makes it possible for code outside your DLL to call the function, because now external code can look up where the function starts. Thus, the function is "exported" in that other people can call it.

RAOF
thank you for wonderful explanation. >C's naming rules, in which the function's name is not mangled.< then how is it going to do the name resolution?
claws
Can you please extend your answer to cover my other questions regarding `Exporting a function from a DLL`
claws
Incompatible name mangling isn't a problem, per se. It's an intentional work-around to the real problem, which is the lack of an application binary interface (ABI) standard. If compilers with incompatible calling conventions (e.g., how exceptions propagate) used the same name-mangling scheme, they would successfully link, but the program would likely crash. Published C++ ABI's always (I think) provide a name-mangling scheme.
Marcelo Cantos
+1  A: 

A properly declared exported function would look like this:

extern "C" __declspec(dllexport)
void __stdcall Foo() {
  // etc...
}

The declarators, in order, do this:

  • extern "C" suppresses C++ name decoration. On a 32-bit machine, the exported name will be _Foo@0, the P/Invoke marshaller has no trouble finding such a name. Without it, the exported name will be ?Foo@@YGXXZ. The marshaller cannot find such a name, you'd have to use the EntryPoint property in the [DllImport] attribute to help it. C++ decorates names like this to support method overloading and type-safe linking.
  • __declspec(dllexport) is a hint to the linker to place the function in the DLL export table. It does the same thing as a .DEF file, without the hassle of maintaining such a file.
  • __stdcall sets the calling convention, the way the arguments are passed to the function. 32-bit code has 5 possible calling conventions (__cdecl, __stdcall, __fastcall, __thiscall, __clrcall). Almost all external software assumes __stdcall as the default, including the P/Invoke marshaller. The default for C/C++ code is however __cdecl. DllImportAttribute.CallingConvention is available to override the default on the managed side.

Your principal tool to troubleshoot this kind of stuff is Dumpbin.exe. Run it from the Visual Studio command prompt on your DLL with the /exports option. It lists the names of the functions found in the export table of the DLL.

You mentioned COM, that's a completely different story. A COM server doesn't export its functions, it uses a "class factory" [sic]. An in-process server exports only 4 functions:

  • DllRegisterServer. Used by Regsvr32.exe to register the server in the registry.
  • DllUnregisterServer. As above, used to remove registration.
  • DllCanUnloadNow. Called by the COM plumbing periodically to check if the server is no longer need and can be unloaded from memory.
  • DllGetClassObject. That's the important one, it is called by COM when the client calls CoCreateObject(). The COM server implements it by creating the COM coclass and returning an interface pointer to the requested interface. Which the COM client then uses to call the methods on the interface. The interface pointer points to a list of function addresses implemented by the interface, much like an interface works in .NET.

Creating these 4 exported function is very commonly the job of whatever class library you use to implement the COM server. The weapon of choice in C++ is ATL.

Hans Passant
well, I'm still learning I didn't get to the stage (in the book) where I should be using "class factory" instead of exporting.
claws