Archive for January, 2008

porting resource compiler .rc files to windres

Thursday, January 31st, 2008

For MinGW, windres is the replacement for the rc resource compiler.  Given a random .rc file, to compile it with MinGW the trick seems to be to insert the following:

// for windres
#include “winresrc.h”
#define IDC_STATIC (-1)

Done.  Handy for cross-compiling these things from Linux.

video loopback in linux

Monday, January 28th, 2008

I’d played around with an earlier version of this video4linux loopback device many years ago, and just found myself needing it again.  In the meantime, it seems to have become a lot better.  Yay!  Much, much more pleasant than the equivalent on Windows…

compiling DirectShow with MinGW on Linux

Thursday, January 24th, 2008

First question: why on earth would you want to do this?  Are you quite mad?

Finding a reason to do this is the hard part, actually doing it is not that bad.  First, start using MinGW on Linux.  That’s fairly straightforward, on Debian/Ubuntu just do “apt-get install mingw32″, then use the i586-mingw32msvc-g++ compiler and its friends in place of regular gcc (this package also places a bunch of other helper programs in the slightly unusual path /usr/i586-mingw32msvc/bin).

Now, follow Samuel Audet’s instructions on using DirectShow from MinGW.

That gets us a lot of the way, but a few more issues show up:

  • Add a definition, _OBJBASE_H_, to your compiler flags
  • Remove superfluous CAggDirectDraw:: qualifier on CAggDirectDraw::~CAggDirectDraw()  in videoctl.h
  • Remove superfluous CTransInPlaceFilter:: qualifier on CTransInPlaceFilter::Copy() in transip.h

While Samuel Audet recycled a project file for compiling, I chose to use CMake.  This isn’t essential of course, but I’ll post the method anyway.  Suppose we want to compile the DirectShow “Ball” example.  I copied the Ball, BaseClasses, and Include directories of the DirectX 9.0 SDK into a common directory, and added a CMakeLists.txt file as follows:

directx_test/

CMakeLists.txt
Ball/
BaseClasses/
Include/

The Ball example generates an activex control, which is just a DLL.  Here is the CMakeLists.txt I used to get this done:

PROJECT(directshower)
FILE(GLOB_RECURSE folder_source *.cpp *.cc *.c)
FILE(GLOB_RECURSE folder_header *.h)
ADD_DEFINITIONS(-D_OBJBASE_H_)
SET(CMAKE_SHARED_LINKER_FLAGS “-Wl,–add-stdcall-alias”)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/Include
${PROJECT_SOURCE_DIR}/Ball
${PROJECT_SOURCE_DIR}/BaseClasses)
LINK_LIBRARIES(advapi32 gdi32 ole32 oleaut32 user32 winmm uuid strmiids)
ADD_LIBRARY(directshower SHARED ${folder_source} ${folder_header})

Other possible libraries to link can be found by inspecting the .dsp files in the project directories.

This compiles and produces a reasonable looking DLL file that, in my case, didn’t actually work straight away as an activex control.  We need to make sure that functions like DllMain, DllRegisterServer, etc are public and “unmangled” in the DLL.  We can check this by typing something like:

 /usr/i586-mingw32msvc/bin/objdump -x libdirectshower.dll | grep DllMain

We want this to give a result like this:

        [   4] DllMain
[   5] DllMain@12
[  8](sec  1)(fl 0×00)(ty  20)(scl   2) (nx 0) 0×000000c0 _DllMainCRTStartup@12
[3978](sec  1)(fl 0×00)(ty  20)(scl   2) (nx 1) 0×000366d0 _DllMain@12

That first line, where the symbol DllMain is present without an underscore before it and without an @ after it, is good, that’s what we want.  That shows that DllMain will be visible on Windows.  You can read about the details at Wu Yongwei’s page on calling conventions.

We need to make sure at least the following functions are visible:

  • DllMain
  • DllGetClassObject
  • DllCanUnloadNow
  • DllRegisterServer
  • DllUnregisterServer

Track all these functions down in the source code.  DllGetClassObject and DllCanUnloadNow are in BaseClasses/dllentry.cpp, the rest are in this case in Ball/fball.cpp.  We need to insert “__declspec(dllexport)” into the declarations of all these methods (there are other possibilities, but this will do for now.  Let’s do:

#define EXPORT __declspec(dllexport)
#define STDAPI_EXPORTED  EXTERN_C EXPORT HRESULT STDAPICALLTYPE

Now, change the signatures of these functions as follows:

STDAPI_EXPORTED DllRegisterServer()
STDAPI_EXPORTED DllUnregisterServer()
STDAPI_EXPORTED DllGetClassObject(REFCLSID rClsID,REFIID riid,void **pv)
STDAPI_EXPORTED DllCanUnloadNow()
EXTERN_C EXPORT BOOL STDAPICALLTYPE DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)

Recompile, check that the symbols are actually visible, copy your .dll to a windows machine, do:

regsvr32.exe  directshower.dll

And boom!  Success!

It seems wrong, somehow…  yet so, so right.

Everyone loves robots!

Tuesday, January 22nd, 2008

Ssh, don’t tell Dalek.  A lot of us here at makesweet.com like robots, so we’re starting to draft a section on them.  But Dalek, because of his name, is rather sensitive about robots and thinks any mention of them is poking fun at him.  So ssssh…

compiling ODE with mingw on linux

Wednesday, January 16th, 2008

The default stack size with mingw on linux seems smaller than the default on windows. This became a problem for me when working with ODE, a dynamics engine that can be a heavy user of the stack. To avoid program crashes on object collisions, I needed to add the following flags to gcc:

-Wl,–stack,0×2000000

This should give a 32M stack size, which I would have expected to be the default for windows.

I was using the mingw32 package on debian.

Update: sometimes the above is not enough, and I’ve had to edit the stack size of a program after it has been compiled, mingw doesn’t seem to set things up right. I’ve used:

editbin.exe /STACK:30000000 the_program.exe

where editbin.exe is a program microsoft supplies for this sort of thing (runs fine under wine). Not sure what a FOSS equivalent of this tool would be.