[Insight-users] How to extend ITK with DLLs at runtime? Defining ITK_AUTOLOAD_PATH crashes every program!

Parag Chandra Parag_Chandra at med . unc . edu
Thu, 15 May 2003 12:01:50 -0400


Thanks for your help Gavin. But now as soon as I define =
ITK_AUTOLOAD_PATH,
every program that I've written that links against ITK dies unexpectedly
inside itk::Directory::Load(). Specifically, at the following line =
inside
the do loop:

    m_Files.push_back(data.name);

I even loaded up the original ITK workspace and tried out the simple =
Image1
example; it too dies at the same location. As soon as I undefine
ITK_AUTOLOAD_PATH, everything works again. I'm not really sure what's =
going
on, because data is completely defined, and data.name is set to '.', =
which
makes sense since that and '..' are the first two entries in any =
directory.
So something goes wrong with the insertion: as I step into
VECTOR::insert(iterator, size_type, const _Ty&), it tries to execute
_Ufill(_Last, _M - (_Last - _P), _X); and dies right there. I really =
can't
make any sense of that; has anyone else encountered this problem when
defining ITK_AUTOLOAD_PATH? I'm running WinXP Pro SP1, MSVC6 with the =
latest
service pack applied (SP5?), VTK 4.2, ITK 1.2, Cmake 1.6.6. The only =
thing
that comes to mind is I had to enable USE_ANSI_STDLIB (or something like
that) when configuring VTK/ITK in order to make ITK and VTK compatible =
with
each other. Would that be the cause?

Best regards,
-Parag=20

-----Original Message-----
From: Gavin Baker [mailto:gavinb+xtk@cs.mu.OZ.AU]=20
Sent: Wednesday, May 14, 2003 8:58 PM
To: Parag Chandra
Cc: insight-users@public.kitware.com
Subject: Re: [Insight-users] How to extend ITK with DLLs at runtime?


Hello Parag,

On Wed, May 14, 2003 at 04:02:35PM -0400, Parag Chandra wrote:

> I am trying to use the DynamicLoader and ObjectFactory mechanism to =
create
> subclasses which can be packaged into shared libraries and then loaded
> dynamically at runtime. I know that the ImageIO framework was designed =
to
> allow this sort of behavior, but I don't understand all the details of =
how
> to make it work. Looking at ImageIOFactory, it's clear that
> ObjectFactoryBase::CreateAllInstance is called in order to create all =
the
> registered subclasses of a particular base class.=20

> Each of these subclasses is then queried to determine which, if any, =
is
> the correct one to handle a particular image format.

The .CanReadFile(...) is called on each ImageIO class (in order of
registration) and the first one to return success gets to load it.

> However, all of these subclasses are essentially linked in statically =
at
> compile time, and their corresponding factories are explicitly =
registered
> via ImageIOFactory::RegisterBuiltInFactories.

These are just the default handlers; you can add your own at any time.

> If I wrote a new ImageIO class and packaged it as a shared library, =
how
> would I get it to automatically register its presence with the master
> ObjectFactoryBase at runtime?

To make an ImageIO 'plugin' for the Frobozz format, you need a few =
essential
elements:

1. A FrobozzImageIOFactory derived from ObjectFactoryBase, that =
registers
   your actual image handler class FrobozzImageIO

2. A FrobozzImageIO derived from ImageIOBase, that implements the normal =

   methods:

        CanReadFile(), Read(), CanWriteFile(), Write()

3. A library initialisation function:

        itk::ObjectFactoryBase* itkLoad()
        {
            return itk::FrobozzImageIOFactory::New();
        }

   that returns a new instance of your factory.

Basically you build the shared library as normal, and drop it into a =
path
somewhere that is pointed to by ITK_AUTOLOAD_PATH (described below).

> There is a mention of ITK_AUTOLOAD_PATH in the documentation; do I =
just
> put the DLL containing the object and its object factory into this =
path?

Yes - you just put the shared object (or DLL as appropriate) somewhere =
on
this path.  This .so should include (at a minimum) the two classes =
mentioned
above.  If you are using an external/3rd party shared library to do the
actual file I/O, obviously this would need to be on the regular path.

> What is this path and how would I modify it? I would really appreciate
> some step-by-step instructions or sample code for accomplishing
> this. Thanks in advance.

It is just an environment variable.  If it is set, the ObjectFactoryBase
will iterate through each path in the list (separated by ; or : =
depending on
platform).  It will try to load any shared libraries it finds (eg. on =
Unix,
"lib*.so") and if there is a function called "itkLoad" it will call it,
expecting to get an ObjectFactory in return.  It will then register this =
new
object factory, which will install your IO handler (as described above).

An example of setting it (under *nix):

    % export ITK_AUTOLOAD_PATH=3D/home/joe/itk/Frobozz/lib

I note that you have already found the bug in the Analyze code [1] - I =
also
reported this a little while ago [2].  I just had a look through CVS and =
it
looks like this was actually fixed in Revision 1.14.2.1 of
itkAnalyzeImageIO.cxx [3] so if you use the CVS release it should work =
fine.

[1] http://www.itk.org/pipermail/insight-users/2003-May/003564.html
[2] http://www.itk.org/pipermail/insight-users/2003-April/003377.html
[3]
http://www.itk.org/cgi-bin/viewcvs.cgi/Code/IO/itkAnalyzeImageIO.cxx.diff=
?r1
=3D1.14&r2=3D1.14.2.1&cvsroot=3DInsight

I have written an ImageIO loader extension for TIFF files using libtiff =
[4],
which was based on one of the existing ImageIO classes in
InsightToolkit/Code/IO.  I will be posting this soon, but I can send you =
an
'alpha' if you like.

[4] http://www.libtiff.org/

I hope this is of some use; let me know how you go... Regards,

  :: Gavin

--=20
Gavin Baker                                Computer Vision Lab (CVMIL)
http://www.cs.mu.oz.au/~gavinb                 University of Melbourne