| |
| Posted by Walter Bright | PermalinkReply |
|
Walter Bright
| Most likely a change in druntime broke this. Windows, obviously.
======================================================
..\dmd -g -d -ofmydll2.dll -version=use_patch mydll2.d dll2.d mydll2.def
std.contracts has been scheduled for deprecation. Please use
std.exception instead.
implib /system mydll2.lib mydll2.dll
Digital Mars Import Library Manager Version 8.41n
Copyright (C) Digital Mars 2000-2004 All Rights Reserved,
www.digitalmars.com
implib/h for help
Input is a Windows NT DLL file 'MYDLL2.DLL'.
Output is a Windows NT import library.
Digital Mars Import Library Creator complete.
..\dmd -g -d testmydll2.d mydll2.lib
testmydll2
hello dll world
hello dll world
---- hangs here ----
================== mydll2.d ==================
module mydll2;
import std.stdio;
version(D_Version2)
{
import core.memory;
}
else
{
import std.gc;
}
export void dllprint()
{
writefln("hello dll world");
}
int glob;
// test access to (tls) globals
export int getglob()
{
return glob;
}
// test gc-mem-allocation from different threads
export char* alloc(int sz)
{
char* p = (new char[sz]).ptr;
version(D_Version2)
GC.addRange(p, sz);
else
addRange(p, p + sz);
return p;
}
export void free(char* p, int sz)
{
version(D_Version2)
GC.removeRange(p);
else
removeRange(p);
// delete p;
}
================== dll2.d =================
// Public Domain
import std.c.windows.windows;
import std.c.stdlib;
version(D_Version2)
{
import core.runtime;
import core.memory;
version(use_patch)
import core.dll_helper;
import core.stdc.string;
extern (C) void _moduleTlsCtor();
extern (C) void _moduleTlsDtor();
}
else
{
import std.gc;
import std.thread;
version(use_patch)
import std.thread_helper;
extern (C)
{
void gc_init();
void gc_term();
void _minit();
void _moduleCtor();
void _moduleDtor();
void _moduleUnitTests();
}
}
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
version(D_Version2)
{
version(use_patch)
{
if( !dll_fixTLS( hInstance, &_tlsstart, &_tlsend,
&_tls_callbacks_a, &_tls_index ) )
return false;
thread_setNeedLock(true);
Runtime.initialize();
// attach to all other threads
enumProcessThreads( function (uint id, void* context) {
if( !Thread.findThread( id ) )
{
thread_attach( id );
thread_moduleTlsCtor( id );
}
return true;
}, null );
}
else
Runtime.initialize();
}
else
{
gc_init(); // initialize GC
_minit(); // initialize module list
_moduleCtor(); // run module constructors
_moduleUnitTests(); // run module unit tests
version(use_patch)
{
// attach to all other threads
enumProcessThreads( function (uint id, void* context) {
if( !Thread._getThreadById( id ) )
Thread.thread_attach( id, OpenThreadHandle( id ),
getThreadStackBottom( id ) );
return true;
}, null );
}
// enumThreads();
}
break;
case DLL_PROCESS_DETACH:
version(D_Version2)
{
version(use_patch)
{
// detach from all other threads
enumProcessThreads(
function (uint id, void* context) {
if( id != GetCurrentThreadId() && Thread.findThread( id ) )
thread_detach( id );
return true;
}, null );
}
Runtime.terminate();
}
else
{
version(use_patch)
{
// detach from all other threads
enumProcessThreads(
function (uint id, void* context) {
if( id != GetCurrentThreadId() )
{
thread_moduleTlsDtor( id );
Thread.thread_detach( id );
}
return true;
}, null );
}
_moduleDtor();
gc_term(); // shut down GC
}
break;
case DLL_THREAD_ATTACH:
version(use_patch)
{
version(D_Version2)
{
thread_attachThis();
_moduleTlsCtor();
}
else
Thread.thread_attach();
}
break;
case DLL_THREAD_DETACH:
version(use_patch)
{
version(D_Version2)
{
if( Thread.findThread( GetCurrentThreadId() ) )
_moduleTlsDtor();
thread_detachThis();
}
else
Thread.thread_detach();
}
break;
}
return true;
}
====================== mydll2.def ================
LIBRARY "mydll2.dll"
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE
===================== testmydll2.d ===================
version(D_Version2)
{
const string d2_shared = " __gshared ";
}
else
{
const string d2_shared = "";
}
version(dynload)
{
extern(Windows) void* LoadLibraryA(in char* dll);
extern(Windows) void* GetProcAddress(void* lib, in char* name);
typedef void fnDllPrint();
typedef int fnGetglob();
typedef char* fnAlloc(int sz);
typedef void fnFree(char* p, int sz);
mixin(d2_shared ~ "fnDllPrint* pDllPrint;");
mixin(d2_shared ~ "fnGetglob* pGetglob;");
mixin(d2_shared ~ "fnAlloc* pAlloc;");
mixin(d2_shared ~ "fnFree* pFree;");
int loadLib()
{
void* lib = LoadLibraryA("mydll2.dll".ptr);
assert(lib);
pDllPrint = cast(fnDllPrint*) GetProcAddress(lib,
"D6mydll28dllprintFZv".ptr);
pFree = cast(fnFree*) GetProcAddress(lib,
"D6mydll24freeFPaiZv".ptr);
pAlloc = cast(fnAlloc*) GetProcAddress(lib,
"D6mydll25allocFiZPa".ptr);
pGetglob = cast(fnGetglob*) GetProcAddress(lib,
"D6mydll27getglobFZi".ptr);
assert(pDllPrint && pFree && pAlloc && pGetglob);
return 0;
}
void dllprint()
{
(*pDllPrint)();
}
int getglob()
{
return (*pGetglob)();
}
char* alloc(int sz)
{
return (*pAlloc)(sz);
}
void free(char* p, int sz)
{
(*pFree)(p, sz);
}
}
else
{
import mydll2;
}
mixin(d2_shared ~ "Object syncobj;");
void runtest()
{
// wait until lib loaded
synchronized(syncobj) getglob();
//int g = mydll.glob;
char*[] mem;
for(int i = 0; i < 10000; i++)
{
mem ~= alloc(16);
}
for(int i = 0; i < 10000; i++)
{
free(mem[i], 16);
}
dllprint();
}
version(D_Version2)
{
import core.thread;
class TestThread : Thread
{
this()
{
super(&runtest);
}
}
}
else
{
import std.thread;
class TestThread : Thread
{
int run()
{
runtest();
return 0;
}
void join()
{
wait();
}
}
}
void test_threaded()
{
syncobj = new Object;
TestThread[] th;
for(int i = 0; i < 10; i++)
th ~= new TestThread();
// don't run threads before lib loaded
synchronized(syncobj)
{
for(int i = 0; i < 5; i++)
th[i].start();
// create some threads before loading the lib, other later
version(dynload) loadLib();
}
for(int i = 5; i < 10; i++)
th[i].start();
for(int i = 0; i < 10; i++)
th[i].join();
}
int main()
{
test_threaded();
return 0;
}
===============================================
|