Quiz of the day: Why does this not work?

TomD t_demmer at nospam.web.de
Thu Nov 6 12:14:47 PST 2008


Hi,
this is about dmd and DLLs.

Given a simple object hierachy in myclasses.d:
module myclasses;
class base{ char[] toString(){ return "I am base";} }
class c1: base{ char[] toString(){ return "I am c1";} }
class c2: base{ char[] toString(){ return "I am c2";} }

and a main file that first does some sanity checks, and then loads and
calls a function in a DLL:

mymain.d:
import tango.sys.SharedLib;

import myclasses;

void main(){
  base[] instances;
  // populate instances
  instances.length=3;
  instances[0] = new base;
  instances[1] = new c1;
  instances[2] = new c2;
  // no problem
  assert( cast(c1) instances[1] !is null);
  assert( cast(c2) instances[2] !is null);

  SharedLib lib = SharedLib.load(`mydll.dll`);
  assert( lib !is null);
  
  extern(C) void function(base[]) my_c_check;
  
  void*  ptr;
  void** point;
  ptr = lib.getSymbol("my_c_check");
  point = cast(void** ) &my_c_check;
  *point = ptr;

  my_c_check( instances );
}

Finally, a DLL that is supposed to work on instances, mydll.d:
import myclasses;
import tango.sys.win32.Types;
import tango.util.log.Trace;

// The core DLL init code, taken from tango wiki.
extern (C) bool  rt_init( void delegate( Exception ) dg = null );
extern (C) bool  rt_term( void delegate( Exception ) dg = null ); 

HINSTANCE g_hInst;

extern (Windows) BOOL 
DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved){
  switch (ulReason){
  case DLL_PROCESS_ATTACH:
    rt_init();
    break;
    
  case DLL_PROCESS_DETACH:
    rt_term();
    break;
    
  case DLL_THREAD_ATTACH:
  case DLL_THREAD_DETACH:
    // Multiple threads not supported yet
    return false;
  }
  g_hInst=hInstance;
  return true;
}
// End of core DLL Init

export extern(C) int my_c_check( base[] instances){
  Trace.formatln("into my_c_check");
  assert( instances.length ==3 );
  Trace.formatln("length check OK");
  assert( instances[0] !is null);
  assert( instances[1] !is null);
  assert( instances[2] !is null);
  Trace.formatln("instances check OK");
  Trace.formatln("instances[0] says: {}", instances[0].toString() );
  Trace.formatln("instances[1] says: {}", instances[1].toString() );
  Trace.formatln("instances[2] says: {}", instances[2].toString() );
  Trace.formatln("instances[0] is: {}", instances[0].classinfo.name );
  Trace.formatln("instances[1] is: {}", instances[1].classinfo.name );
  Trace.formatln("instances[2] is: {}", instances[2].classinfo.name );
  // Boom!
  assert( cast(c1) instances[1] !is null);
  assert( cast(c2) instances[2] !is null);

  return 0;
}

This is a real show stopper for using D with/for dynamic libraries.
Is there anything simple to fix this?

Ciao
Tom



More information about the Digitalmars-d mailing list