NN – WordPress

September 29, 2008

Registration free COM

Filed under: c++, com — by NN @ 4:59 am

So this will be the first post, not the last, about registration free COM.
Btw co is short of COM. Why ??

The beginning is taken from KK’s blog:Registration free COM .

So what do we do:
1. Create an IDL file describing our interfaces.
2. Compile it with midl to produce for us the definitions of the interface and proxy-stub.
3. The server application uses the generated .c files and just call CoRegisterClassObject in the beginning for the factory and then registers the proxy-stub.
4. The client registers the proxy-stub and then just call naturally CoCreateInstance.
5. It works.

Some to make work.
There is a standard marshalling for standard interfaces: IPersist, IStorage, IClassFactory …
What it tells us ? That we can marshall IClassFactory for free.
So we create a global instance of our ClassFactory implementation and then register it using CoRegisterClassObject.
That’s all what is needed to make class factory in the client ! :)

The only problem that you first create a ClassFactory and then you call manually CreateInstance… Not good.

Again we have a problem.
And the brilliant solution !
If you remember [coclass] in IDL describes some class which implements the interfaces.
What if you tells that coclass implements your interface and ClassFactory too ? Hmm.

[uuid("...")]
coclass A
{
[default] interface IA;
interface IClassFactory
}

This is the trick :)
When we call CoCreateInstance in the client:
CoCreateInstance(CLSID_A, … IID_A..);
It looks for ClassFactory and finds it ! Then it calls CreateInstance of our ClassFactory implementation which creates IA implementation class.
So simple :)

Now, since the creation is the regular COM instance creation you can simply use the class in .Net like this:
A a = new AClass();

That’s all for today.

P.S.
The source code will be supplied later.

September 21, 2008

C++ & GUI

Filed under: c++ — by NN @ 7:16 pm

I have written some applications in C++ with GUI for Windows.

I have used WinAPI then MFC and the last was WTL.

But what lacks is the graphical designer. I know there is resource editor with dialogs but dialog is not a regular window and so on.

Currently I have to write some GUI application and of course it must be very small in size, so C++ seems a possible solutoin. But I want a GUI designer !

Neither MFC nor WTL provide a good GUI designer to create windows, only dialogs. :(

So what do we have today:

1. wxWidgets

wxGlade is a designer for this library


It can generate C++ code as well.

2. FLTK
fluid is the GUI designer:

3. SmartWin++
Sally is a nice IDE:

I still do not know which library is the best, since designer solve all the problems for GUI code generation :)
wxWidgets is the preferred but I may go on FLTK because I need a small executable.
Somewhen you will know.

April 11, 2008

VC++ 9.0, msvcrt.dll, Windows 95

Filed under: c++ — by NN @ 11:56 am

 Prelude:

VC++ 9.0 is a nice compiler but since VC++ 7.0 the binary does not use msvcrt.dll for dynamic build.

So solutions:

1.       Provide installer for mvcr90.dll

2.       Compile static build

Both solutions are not reasonable sometimes. The solution 1 cannot be used for ActiveX controls because there is undoubtedly no VC++ 9.0 runtime in all computers. The solution 2 is not usable when you want the same heap in executable and in your dll or in two dlls.

The solution:

We use the trick from Dynamically linking with MSVCRT.DLL using Visual C++ 2005.

First, download VC++ 9.0 express (it is free and legal to use J). Download it here: http://www.microsoft.com/express/.

Second, download Windows Driver Kit (WDK). Download it here: https://connect.microsoft.com/Downloads/DownloadDetails.aspx?SiteID=148&DownloadID=11295

We are ready to go.

1.       Create a project

2.       Select release configuration.

3.       Set additional include directories to C:\WinDDK\<WDK_VERSION>\inc\crt. You cannot use VC++ crt directory!

4.        Set additional library directories to C:\WinDDK\<WDK_VERSION>\lib\w2k\i386

5.       Add to additional libraries msvcrt_win2000.obj

6.       Compile.

That’s all. Now your program is dependent only on msvcrt.dll !

 

Problems:

No debug?

Yes there is no msvcrtd.dll for msvcrtd.lib which supplied with WDK. Maybe it is intentional, maybe not.

It doesn’t say that you cannot compile debug, it just says that you must not use debug macros from CRT like _ASSERT, assert and so on.

You can implement these macros by yourself and this works.

RunTime Checks

It is easy, just set the compiler flags.

The only problem you may notice is compiling static build with RunTime Checks.

There is same function _crt_debugger_hook in RunTmChk.lib from VC++ and libcmtd.lib from WDK.

The solution is simple, patch RuTmChk.lib (replace the name to e.g. _crt_debugger_hoox ) and move it to patched\RuTmChk.lib. Then add patched directory to additional library directories. Now RunTime Checks work with static build.

CRT_RTC_INITW

You may see that linker cannot find _CRT_RTC_INIT function when you compile in debug.

The implementation is very easy, you just need to implement _CrtDbgReportW by yourself (You have the sources in Visual Studio 2008 ) and return this function.

ATL

No problems! Just use ATL from WDK ( C:\WinDDK\<WDK_VERSION>\inc\crt\atl71 ) and library from C:\WinDDK\<WDK_VERSION>\lib\atl\i386

Notice that ATL must not be compiled in debug.

Just undefine _DEBUG macro before including atlbase.h:

#pragma push_macro(“_DEBUG”)

#undef _DEBUG

#include <atlbase.h>

#pragma pop_macro(“_DEBUG”)

You need also to define your own implementation of ATLASSERT, otherwise it uses _ASSERTE which cannot be used in our case.

It is not ATL 8.0 nor ATL 9.0 but it is better than nothing J

Standard C++ Library

You cannot use the VC++ headers because they rely on VC++ 9.0 CRT, so they are not usable.

You may use other Standard C++ Library implementation like STLPort. (http://stlport.org/download.html )

You need some special defines to make STLPort work correctly like:

_STLP_HAS_NO_NEW_C_HEADERS

_STLP_GLOBAL_NEW_HANDLER

_STLP_VENDOR_TERMINATE_STD=

And some more till you have your code compiled well. (Just read the readme files of STLPort)

You may compile STLPort if you want to use Standard C++ streams.

Windows 9x:

Visual C++ 9.0 does not support Windows 9x at all. In fact the only support is for Windows 2000 and above.

But what miserable Windows 9x users should do? Use old versions of VC++? No!!

Investigation:

When you run the compiled executable which uses only msvcrt.dll it doesn’t work because you have message box about unsupported Operating System.

This happens because of linker. Linker from VC++ 9.0 sets minimum Operating System to 5.0 and SubSystem version to 5.0. There /SUBSYSTEM flag  does not allow to set the number below 5.0.

The simplest solution is just to patch the executable and change 5.0 to 4.0 J

After that the executable runs smoothly in Windows 98, but not Windows 95.

Windows 95:

The only reason why Windows 95 cannot be supported is use of InterlockedCompareExchange in CRT startup code!!

It can be solved very simple. You just “paste” the code of InterlockedCompareExchange instead of function call and change ImportAddressTable to not point to InterlockedCompareExchange.

 

More detailed information about Windows 95:

 

Compile a simple program: int main(){}

Now if you disassemble your program you will see the following code:

53 push ebx ; Comperand
56 push esi ; Exchange
57 push edi ; Destination
FF 15 24 20 40 00 call ds:InterlockedCompareExchange

This code is created by linker, so you cannot control it.
Now we just have to replace call with direct call:

InterlockedCompareExchange implementation (in kernel32.dll):

InterlockedCompareExchange proc near

;Destination = dword ptr 4
;Exchange = dword ptr 8
;Comperand = dword ptr 0Ch

mov ecx, [esp+4]
mov edx, [esp+8]
mov eax, [esp+0Ch]
lock cmpxchg [ecx], edx
retn 0Ch
InterlockedCompareExchange endp

Now the replacement:

mov ecx, [edi]
mov edx, [esi]
mov eax, ebx
lock cmpxchg [ecx], edx

It will be better to reduce the size:
8B 16 mov edx,dword ptr [esi]
8B C3 mov eax,ebx
F0 0F B1 17 lock cmpxchg dword ptr [edi],edx
90 nop

The next thing is to remove InterlockedCompareExchange from Import Table.
I just replace it with InterlockedIncrement:
Find it using your favourite hex editor (I use HxD, it is free ) )
Replace InterlockedCompareExchange with InterlockedIncrement, fill zeroes to match the same size.
Now look at the number of the function, it is BA 02 (02BAh). (It is before the name)
InterlockedIncrement has other number: 02C0h.
Just set the number.

That’s all.

And of course do not forget to update exe checksum even if no one checks it ) 

 

 

Conclusions:

You can use Visual C++ Express 2008 and run your code even in Windows 95 without too much effort.

Why Microsoft doesn’t want us to be able to compile for Windows 9x?

The answer is simple;  it costs money to support old and buggy Operating Systems.

Enjoy.

 

P.S.

I didn’t dive into technical details of every small thing.

You may ask questions about the specific detail, if it is needed.

Thanx to KK

P.P.S.

If I have written something wrong here, tell me )

April 9, 2008

Foreach revisited

Filed under: c++ — by NN @ 8:31 am

Here I talked about for each keyword.
But it didn’t work with references and other good stuff.

Here i have posted some for each solution which supports references and even string literals.
The only disadvantage compared to boost version is lack of support for noncopyable and rvalues even if compiler does support it.

But the code much more optimal than boost version.
Enjoy.

January 1, 2008

Boost.TypeTraits

Filed under: boost, c++ — by NN @ 10:11 am

This is very nice library BUT it is compiled very slowly !! Especially if you include <boost/type_traits.hpp>

Beware !

So I had to write my own implementation of is_*** since boost is slow :(

October 19, 2007

C++ foreach

Filed under: boost, c++ — by NN @ 9:31 pm
Tags: ,

Many people use containers with begin and end methods.

I do not love for loops for iterating over containers, it is very ugly and not maintanable.

The past solution was to use std::for_each + functors.

It can be good, but thus you need to define a global helper class for a small thing. So many used to create highly extendable class that do anything.

And of course there is std::bind1st, std::bind2nd, std::mem_fun, std::ptr_fun ugliness. Do not use it !!

And there is boost::bind the great thing, and boost::lambda the thing.  I love the both. They help you to write a short code which does what it meant to be and you have a local function.

But still you cannot do all using boost::lambda , perhaps it compiles slow and produces not optimizable code.

The only solution for optimizing is to use loop.. Not now !

Boost has Boost.Foreach library which helps you to iterate in a very neat way over the container/built in array type/string literal. All what you need. But it is Boost and it is macro, and it does not provide an optimizable code even if it is better than Boost.Lambda.

The story begins with discovery of for each in VC8. VC8 has C++/CLI which must have for each to iterate over System::Array or any type derived from System::IEnumerator. But in fact for each works on Native programs too.

Even more it produces the same code like for. And it can be used with Standard Library !

Wow !

The happiness is good but it has disadvantage, it cannot get reference in the item type.

After seeking for a solution for this, and for full replacement to BOOST_FOREACH which can use Boost.Range for extandability. I have found a solution.

In Boost – Ticket #1295 there is my solution for foreach which uses advantage of VC 8 and later.

Update:
foreach for poor, it is implementation of for each which passes almost all boost.foreach tests except noncopyable, rvalue_const, rvalue_nonconst.
Enjoy :)

Update2:

If you lucky user of VC 9.0 or even VC 9.0 SP1you may have paid attention that BOOST_FOREACH produces exactly the same code like ugly hand-writed for loop, and i mean the for loop with end caching which many forget to do !

So there is no need for MS specific for each at all. Just use VC 9.0 SP1 :)

No copy – no problem

Filed under: boost, c++ — by NN @ 12:10 pm
Tags: ,

C strikes C++ when it is need to work on the prepared data in the memory.

C++ has no good way of bewaring copies.

E.g. we have a prepared array:

int i[10];

and we have a function

void f(std::vector<int>& o);

We cannot pass the array into the function without copying ! Sux.

So if your library has a bad design, like this before. You stuck with copies, and you have nothing to do.

The only solution is a good design for your library, and of course C++ Standard Library has a good design to allow you not to do copies !

So what the solution ? As do you understand clearly – Iterators !

Instead of writing:

void f(std::vector<int>& o)

Write:

void f(int* first, int* last);

Yes, of course, this is not what you want, but now you do not have to copy. Heh, of course this is not a solution, it yucks with ugly pointers. And you have no meaning if you need to allocate or deallocate the memory.

So you want template ?

template<typename T> void f(T first, T last)

Not good too, it is template, so cannot be virtual function and it has 2 arguments instead of one.

So the perfect solution is range. Range it is concept of keeping two iterators for first and last.

Of course boost has iterator_range which can be used.

Something like:

void f(iterator_range<int> r)

Of course we may need implicit creation of iterator_range from vector if we do not want to change code too much.

But we still stucked if we want to use the vector methods, like index operator, or anything else. What we need is an ultimate range which can behave like vector still being not vector.

Since boost::iterator_range supports all what we need it can be some perfect solution.

Added:

Of course in each solution there is a disadvantage. As you can see in this link: http://boost.org/libs/range/doc/utility_class.html

boost::iterator_range and boost::sub_range receives an iterator rather than type, so u cannot write a function of all types of iterators unless it is template.

But you can always use the specialized version: void f(boost::iterator_range<int*> const& r).

Powered by WordPress.com