|
The extern "C" declaration is used to tell the C++ compiler not to mangle the symbol which is being declared.
When the C++ compiler encounters a function name like "DisplayCurrentThreadId()" which has not been declared as extern "C", it will emit a symbol for it which will look like the following :
?DisplayCurrentThreadId@@YAXXZ
The actual symbol produced depends on the compiler used (the above was produced by VC++ 6.0). This symbol will be used in the resulting OBJ file for linking purposes.
C++ has a variety of reasons for symbol name mangling, of course. But the reason for the mangling of function names (both class functions and global ones) is to enable function name overloading (i.e. using the same function name with different parameter types).
If extern "C" was used to declare the function, the symbol produced for it could be:
_DisplayCurrentThreadId
This depends on the compiler used. But the bottom line is that no function name overloading will be allowed (since the C language does not support this, hence extern "C").
|
|
|
|
|
i am glad that i can learn about the real functionality of using exern"C" which i used to use without truly understanding-- just use it like like other people do.
|
|
|
|
|
1. A Proxy/Stub DLL is always required under one of the following situations :
1.1 Your COM object resides in an EXE Server.
Further note the following :
1.1.1 This is where the use of marshalling is most natural.
1.1.2 In order for your client (a separate EXE application) to use your COM object, marshalling is required.
1.2 Your COM object resides in a DLL Server.
Further note the following :
1.2.1 A COM object will always be used by a thread in a client application.
1.2.2 A client thread which uses COM will always reside in an apartment.
1.2.3 A COM object will also always reside in an apartment.
1.2.3 If the apartment of a client thread which uses a COM object is not the same the apartment of the COM object, marshalling will be required.
To put things simply, where a COM object is accessed across threads (be it threads of a single process or threads across processes), marshalling may be involved.
2. Even when you are using OLE-automation-compatible types, marshalling will be involved.
2.1 In this case, the standard COM marshaller is used. However, note carefully :
2.1.1 That this is provided that your interface has been assigned the [dual] or the [oleautomation] attribute.
2.1.2 If not, your interface cannot be marshaled using the standard COM marshaler.
2.2 The standard COM marshaler is oleaut32.dll (the standard Proxy/Stub DLL for Ole Automation).
2.2 In this case, you do not have to build any Proxy/Stub DLL in order for your clients to use your interface.
3. If your interface uses non-OLE-automation-compatible types as parameters, or that it uses OLE-automation-compatible parameter types but that it is not marked with the [dual] or [oleautomation] attributes, you would definitely need a Proxy/Stub DLL.
3.1 Note that your Proxy/Stub DLL is meant to be used for interfaces and not implementations.
3.2 For example, if you have an interface IAnInterface, say. And you have two implementations of IAnInterface in two separate DLLs, the two implementations will use the same Proxy/Stub DLL.
3.3 Every interface that is ever defined in a Windows OS will have an entry in the registry (under the HKEY_CLASSES_ROOT\Interface Key). They are registered under their GUIDs.
3.4 You will notice that many of the interface entries have a "ProxyStubClsid32" subkey.
3.5 This subkey contains a GUID which identifies the Proxy/Stub DLL associated with this Interface.
4. If you use the MIDL compiler, the source codes for building a Proxy/Stub DLL for your interface can be generated for you.
4.1 The followig files, generated by the MIDL compiler, are the raw materials for your Proxy/Stub :
- *_i.c
- *_p.c
- dlldata.c
where * denotes the name of your COM project.
The *_i.c file contains the actual definitions of the IIDs and CLSIDs defined in your COM project IDL file.
The *_p.c file contains proxy/stub data specific to the interfaces defined in your IDL file.
The dlldata.c file contains macros and code that help to generate basic COM DLL requirements (e.g. DllCanUnloadNow(), DllGetClassObject(), etc).
4.2 Start Visual C++ and create a basic Win32 DLL (non-MFC and non-ATL) project.
4.3 Add the *_i.c, *_p.c and dlldata.c files into this project.
4.4 Create your own .DEF file which should contain the following definitions :
LIBRARY <YOUR MODULE NAME>
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
GetProxyDllInfo
4.5 You will need to supply the following pre-processor definitions to your project :
- REGISTER_PROXY_DLL
- either _WIN32_WINNT=0x400
- or _WIN32_WINNT=0x500 (if any interfaces has async_uuid attribute)
The REGISTER_PROXY_DLL definition will ensure that two of the basic COM DLL required exported functions DllRegisterServer() and DllUnregisterServer() are generated within dlldata.c.
The "_WIN32_WINNT=0x400" or "_WIN32_WINNT=0x500" is required otherwise you will face several compilation errors.
If any interface has been attributed with "async_uuid" then you will also need to use the correct-versioned "rpcproxy.h" file. If you are not using the correct-versioned one, the compiler will complain of this. The latest MS SDK include directory usually will contain the latest version of "rpcproxy.h". To use this, set $(MSSDK)\include in your "Additional include directories" path (under project settings).
4.6 Your project will also need to link to rpcrt4.lib.
4.7 After building a successful Proxy/Stub DLL project, you must remember to register this DLL.
<div class="ForumMod">modified on Thursday, January 29, 2009 12:31 AM</div>
|
|
|
|
|
2007 May 3rd
-------------
More notes :
1. Note that it is the Proxy/Stub DLL which generates the appropriate information for a non-OLE-automation-compatible (i.e. custom) interface. This includes the GUID and name of the interface, the number of methods it exposes, etc.
2. When the Proxy/Stub DLL is registered, it officially writes these Interface information in the registry (inside the custom interface's entry under the HKEY_CLASSES_ROOT\Interface registry key). The DLL also registers the GUID of the Proxy/Stub DLL (i.e. itself) associated with each custom interface.
3. In order to enable the Proxy/Stub DLL to contain such information, the Interface as defined in the original IDL must be declared outside the "library" block.
4. The best practice is to define the interface outside the library block and then reference that interface from inside the library block, as shown in this example:
//file: AllKnown.idl
[
object, uuid(. . .), <other interface="" attributes="">
]
interface IKnown : IUnknown
{
import "unknwn.idl";
<declarations,>
};
[
<library attributes="">]
library KnownLibrary
{
//reference interface IKnown:
interface IKnown;
//or create a new class:
[
<coclass attributes="">
]
coclass KnowMore
{
interface IKnown;
};
};
[example above taken from MSDN]
5. Note that the original Type Library whose compile-time IDL-file being the one in which the custom interface was originally defined, would not be able to generate the information mentioned in point 1 above for the custom interface. This is because it has no knowledge of the GUID of the Proxy/Stub which will be associated with the custom interface.
6. Note also that for custom interfaces, the type library is not needed. In fact, type libraries are not relevant for them to be used by a client.
modified on Friday, June 20, 2008 6:01 AM
|
|
|
|
|
2008 June 20th
---------------
More Notes :
1. I noticed that if a proxy/stub DLL has been generated for an interface that is oleautomation compatible (i.e. dual or oleautomation attributes have been assigned to the interface), then the proxy/stub DLL will be used even if the Universal Marshaler (i.e. OLEAUT32.DLL) could have been used (assuming of course that the interface has been defined inside a Type Library and that the Type Library has been registered).
2. However, if that proxy/stub DLL is not registered, the Type Library will be used.
3. Note however, that re-registration and/or recompilation of the Type Library and COM Server code may be necessary to effect a switch around.
|
|
|
|
|
// Here is an example of using mem_fun1 together with bind1st()
// to call a member function of a class which has been instantiated.
// The basic objective is to be able to call the for_each() algorithm
// with the use of a member function of an object as the target function
// to be called on each item in the container.
#include <set>
#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class myClass
{
public :
// Note : parameter pString must not be a pointer
// nor a reference.
int DoSomethingWithString( std::string pString )
{
cout << pString.c_str() << endl;
return 0;
}
public:
void Go()
{
std::set<std::string> myStrings;
myStrings.insert("ABC");
myStrings.insert("DEF");
myStrings.insert("GHI");
std::for_each
(
myStrings.begin(),
myStrings.end(),
// Here is the challenging usage of bind1st and mem_fun1.
std::bind1st(std::mem_fun1(&myClass::DoSomethingWithString), this)
);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
myClass mc;
mc.Go();
return 0;
}
|
|
|
|
|
Another way to achieve the use of a member function in such a situation is to declare a class deriving from std::string :
class MyString : public std::string
{
public :
MyString()
{
}
MyString(const char* pstring) :
std::string(pstring)
{
}
~MyString()
{
}
void DoSomethingWithString()
{
std::cout << c_str() << std::endl;
}
};
You basically extend the std::string with a public member function named DoSomethingWithString().
Then in myClass::Go(), you use MyString instead of std::string :
void Go()
{
std::set<MyString> myStrings;
myStrings.insert("ABC");
myStrings.insert("DEF");
myStrings.insert("GHI");
std::for_each
(
myStrings.begin(),
myStrings.end(),
mem_fun_ref(&MyString::DoSomethingWithString)
);
}
Use mem_fun_ref() as the predicate for for_each(). Basically, MyString::DoSomethingWithString() wsill be called on each contained object in myStrings (which is a set of MyString objects).
|
|
|
|
|
It seems best to install CDT via the "Software Updates" facility of the eclipse IDE.
Use the following URL in a Site Bookmark in the update manager:
http://download.eclipse.org/tools/cdt/releases/eclipse3.1
To install CDT from the update site, in the Help menu select Software Updates and then Find and Install, Select Search for new features to install and click Next. Click New Remote Site to add an update with the URL provided above, and then expand the site node to reveal the available downloads.
|
|
|
|
|
Note
-----
When you build your project, you can choose a MinSize or MinDependency configuration. MinSize will generate a smaller component, since shared code will be used from Atl.dll. In this case, you must distribute Atl.dll with your component. MinDependency will generate a larger component, since all necessary code will be linked in with your component.
Note
-----
When building a Release version of a project, you can get the following link error:
LIBCMT.LIB(crt0.obj) : error LNK2001: unresolved external symbol _main
This error occurs if you are using CRT functions that require CRT startup code. The Release configurations define _ATL_MIN_CRT, which excludes CRT startup code from your EXE or DLL. To avoid this error, do one of the following:
Remove _ATL_MIN_CRT from the list of preprocessor defines to allow CRT startup code to be included. On the Project menu, click Settings. In the Settings For: drop-down list, choose Multiple Configurations. In the Select project configuration(s) to modify dialog box that appears, click the check boxes for all Release versions, and then click OK. On the C/C++ tab, choose the General category, then remove _ATL_MIN_CRT from the Preprocessor definitions edit box.
If possible, remove calls to CRT functions that require CRT startup code and use their Win32 equivalents. For example, use lstrcmp instead of strcmp. Known functions that require CRT startup code are some of the string and floating point functions.
|
|
|
|
|
Q : Why do I get a "LNK2001: unresolved external symbol _main" error or "LNK2001: unresolved external symbol _WinMain" when I try to build my application?
A : This usually happens when you create the wrong type of project for you application. In the first case, you chose "Win32 Application" when you should have selected "Win32 Console Application". On the second case, well, it's the other way.
There are two ways to fix it: (1) Create a new project of the correct type, and readd all your files too it, or (2) change the type of the current project. This can be easily accomplished. Select Project -> Settings from the menu, and go to the Link tab. There, in the edit control at the bottom, look for the /subsystem switch and change it to "/subsystem:console" or "/subsystem:windows" as appropriate.
|
|
|
|
|
Hi all,
does anybody knows if it is possible to have different behaviour of a function in template classes ?
I need to control the flow in differen cases.
I need something like this example (where I used a pseudo code format)
template <typename MYTYPE>class CMyClass{
MYTYPE var;
...
void fun(){
CString str;
//Flow contol !!
if(MYTYPE == int) str.Format("%d",var);
if(MYTYPE == float) str.Format("%f",var);
if(MYTYPE ???) str="Unable format conversion";
}
...
}
|
|
|
|
|
Hello _Russell_,
What you need is known as "explicit template specialization". Define each specialized version of "void fun()" as follows :
void CMyClass<int>::fun()
{
str.Format("%d", var);
}
void CMyClass<float>::fun()
{
str.Format("%f", var);
}
Best Regards,
Bio.
|
|
|
|
|
You also need to put template<> before explicit specializations.
--Mike--
|
|
|
|
|
Thanks friends,
It works.
But let me know if are possible other solutions, expecially if exist a way similar to the way that I used in the first message (if it exist then in some cases it can be a very fast way to write code!)
|
|
|
|
|
Yes, you can use a policy-based design as one way to solve this:
template <class T> struct format_string
{
LPCTSTR get_string() { assert(false); }
};
template<> struct format_string<int>
{
LPCTSTR get_string() { return _T("%d"); }
};
template<> struct format_string<float>
{
LPCTSTR get_string() { return _T("%f"); }
};
template<class T, class policy=format_string<T> >
class foo
{
public: void fun() { CString s = policy::get_string();}
};
--Mike--
|
|
|
|
|
Is there a way i can contact you, Lim? I can be reached at jubithn@nway.in
Regards
Jubith Nambradth
|
|
|
|
|
Operator new allocates memory from the heap, on which an object is constructed. Standard C++ also supports placement new operator, which constructs an object on a pre-allocated buffer. This is useful when building a memory pool, a garbage collector or simply when performance and exception safety are paramount (there's no danger of allocation failure since the memory has already been allocated, and constructing an object on a pre-allocated buffer takes less time):
void placement() {
char *buf = new char[1000]; //pre-allocated buffer
string *p = new (buf) string("hi"); //placement new
string *q = new string("hi"); //ordinary heap allocation
cout
|
|
|
|
|
Placement New/Delete
In C++, operators new/delete mostly replace the use of malloc() and free() in C. For example:
class A {
public:
A();
~A();
};
A* p = new A;
...
delete p;
allocates storage for an A object and arranges for its constructor to be called, later followed by invocation of the destructor and freeing of the storage. You can use the standard new/delete functions in the library, or define your own globally and/or on a per-class basis.
There's a variation on new/delete worth mentioning. It's possible to supply additional parameters to a new call, for example:
A* p = new (a, b) A;
where a and b are arbitrary expressions; this is known as "placement new". For example, suppose that you have an object instance of a specialized class named Alloc that you want to pass to the new operator, so that new can control allocation according to the state of this object (that is, a specialized storage allocator):
class Alloc {/* stuff */};
Alloc allocator;
...
class A {/* stuff */};
...
A* p = new (allocator) A;
If you do this, then you need to define your own new function, like this:
void* operator new(size_t s, Alloc& a)
{
// stuff
}
The first parameter is always of type "size_t" (typically unsigned int), and any additional parameters are then listed. In this example, the "a" instance of Alloc might be examined to determine what strategy to use to allocate space. A similar approach can be used for operator new[] used for arrays.
This feature has been around for a while. A relatively new feature that goes along with it is placement delete. If during object initialization as part of a placement new call, for example during constructor invocation on a class object instance, an exception is thrown, then a matching placement delete call is made, with the same arguments and values as to placement new. In the example above, a matching function would be:
void operator delete(void* p, Alloc& a)
{
// stuff
}
With new, the first parameter is always "size_t", and with delete, always "void*". So "matching" in this instance means all other parameters match. "a" would have the value as was passed to new earlier.
Here's a simple example:
int flag = 0;
typedef unsigned int size_t;
void operator delete(void* p, int i)
{
flag = 1;
}
void* operator new(size_t s, int i)
{
return new char[s];
}
class A {
public:
A() {throw -37;}
};
int main()
{
try {
A* p = new (1234) A;
}
catch (int i) {
}
if (flag == 0)
return 1;
else
return 0;
}
Placement delete may not be in your local C++ compiler as yet. In compilers without this feature, memory will leak. Note also that you can't call overloaded operator delete directly via the operator syntax; you'd have to code it as a regular function call.
[from web page : http://www.glenmccl.com/tip_025.htm[^]]
|
|
|
|
|
1. Windows XP SP2.
2. Firewall on. Open Port TCP 135 and optionally Port UDP 135.
-- modified at 3:31 Thursday 16th February, 2006
|
|
|
|
|
There are 2 points I recently discovered about using comments in an INI file :
1. Comments must occupy a sinle line and not be part of a <lhs>=<value> string. For example :
[TEST]
TEST=abc ; abc
The value for "TEST" is actually "abc ; abc"
2. It seems the semi-colon (;) is the official comment-start character. Hence you cannot name a <lhs> as ";TEST" but you can name one as "#TEST".
|
|
|
|
|
If you try to instantiate a VB Active X Control (e.g. MSWINSCK.OCX) and get the CLASS_E_NOTLICENSED (0x80040112L) error, it could really be due to the fact that the license for using the control is not installed in the target machine.
One way to resolve this is to install the VB IDE in the target machine. If this is not an option, create an installation prgram via the VB supplied setup system. The licences for using the VB controls will then be installed on the target system.
|
|
|
|
|
Hi,
I made a com component in C# but I don't know how to call it from a VC++ environment(the steps to register it ,etc..)
Thanks
emmy
|
|
|
|
|
Hello meesho,
Just like a normal COM DLL or EXE, a .NET module which has been wrapped as a COM module needs to have its information written into the registry in order for the COM sub-system to locate it and load it into memory for a client.
REGASM.EXE
----------
This is achieved via the REGASM.EXE utility. REGASM performs similarly to the well-known REGSVR32.EXE utility which is used to register COM modules. REGASM uses the metadata contained inside a .NET assembly to generate COM-equivalent information which are then used to insert entries into the registry.
The entries written into the registry include the CLSIDs and ProgIDs of .NET classes which are exposed as COM classes. This registration process is important for COM clients in the discovery and loading process.
Call the REGASM.EXE utility inside the Visual Studio .NET command prompt as folows :
regasm <.NET DLL Assembly Name> /tlb
The "/tlb" flag commands REGASM.EXE to produce a Type Library File (.TLB) for the .NET Assembly. It is useful for your VC++ client to import.
In your VC++ code, you import the .TLB file using the #import keyword, e.g. :
#import "(TLB file path)";
GACUTIL.EXE
-----------
Next, for ease of discovery and loading by the .NET CLR engine, your .NET DLL Assembly -should- be registered into the GAC (Global Assembly Cache). This is not 100% required but will make life must easiler for your client apps.
In order that a .NET module be registered to the GAC, it needs to be digitally signed. This requires a Strong Name Key (SNK) file. You can create an SNK file using the "sn.exe" .NET utility.
Another step to take is to set the path of the SNK file in the AssemblyKeyFile attribute in the AssemblyInfo.cs file :
[assembly: AssemblyKeyFile("..\\..\\KeyFile.snk")]
To register an assembly into the GAC, we use the GACUTIL.EXE utility. For example :
gacutil -i <.NET DLL Assembly Name>
An alternative to using GACUTIL.EXE is to copy your DLL Assembly into a folder location that can be discovered by the .NET CLR.
Give it all a try, meesho. Let me know if you need further clarifications.
Best Regards,
Bio.
|
|
|
|
|
.NET Components working as COM Objects (wrapped inside COM-Callable Wrappers) are designated being able to survive as STA or MTA objects. That is they support "BOTH" apartment types.
-- modified at 18:47 Friday 25th November, 2005
|
|
|
|
|
mysteron 11/10/2005 11:31 AM PST
I was reading somewhere that 'every STA needs it's own message pump' .. does
this also apply to the scenario where an *inproc* object creates a bunch of
worker threads (and makes those threads STA's by calling CoInitalize(NULL))
.... I have a test app here that is an inproc control that does just this ..
spawns a bunch of worker threads, makes them into STA's and marshals
interfaces into them from the main STA .. and there's only one message pump
pumping.. out in the container app ... and it all seems to work just fine...
TIA
|
|
|
|
|