Re: Empty LST files?

2016-07-31 Thread Thalamus via Digitalmars-d-learn

On Sunday, 31 July 2016 at 17:01:32 UTC, Seb wrote:

On Sunday, 31 July 2016 at 16:55:52 UTC, Seb wrote:

On Sunday, 31 July 2016 at 16:48:52 UTC, Thalamus wrote:

On Sunday, 31 July 2016 at 16:08:49 UTC, Seb wrote:

On Sunday, 31 July 2016 at 15:30:46 UTC, Thalamus wrote:

[...]


How about setting the source path directly? With a recent 
enough dmd version this can be done automatically like here:

https://github.com/dlang/dmd/pull/5990/files


Thanks Seb. Has this been included in an official version 
release yet? (I'm not sure how to tell. I've only used Git a 
small amount.)


thanks!


Nope it has been added five days ago.
You might grab a dmd-nightly build from here 
https://dlang.org/download.html


To clarify I am talking about ___FILE_FULL_PATH__, maybe 
hard-coding the source directory could also work for you?


In the end, I elected to go with a separate solution for test 
EXEs with the project hierarchy echoed as solution folders. 
Although this adds some extra overhead to maintain this echo, 
that can be automated as part of the main solution's build. And 
it seems to me that there are inherent advantages to going this 
route. For instance, were this all still in one solution, I'd 
either have to add additional configurations (32-bit w/ -cov, and 
64-bit w/ -cov), or I'd have to manually add -cov to each project 
whenever I wanted coverage info and later remove it, or I'd have 
to wait for the code coverage files to be created after every 
run. A separate solution allows me to maintain -cov for all 
configurations isolated from my main development mode. So it's 
there when I want it and gone when I don't, seamlessly.


Thanks to everyone for their input!



Re: Empty LST files?

2016-07-31 Thread Thalamus via Digitalmars-d-learn

On Sunday, 31 July 2016 at 16:08:49 UTC, Seb wrote:

On Sunday, 31 July 2016 at 15:30:46 UTC, Thalamus wrote:

On Sunday, 31 July 2016 at 14:03:49 UTC, Thalamus wrote:

[...]


After a couple more hours today, I found a couple of 
solutions. Neither is satisfactory.


[...]


How about setting the source path directly? With a recent 
enough dmd version this can be done automatically like here:

https://github.com/dlang/dmd/pull/5990/files


Thanks Seb. Has this been included in an official version release 
yet? (I'm not sure how to tell. I've only used Git a small 
amount.)


thanks!



Re: Empty LST files?

2016-07-31 Thread Thalamus via Digitalmars-d-learn

On Sunday, 31 July 2016 at 14:03:49 UTC, Thalamus wrote:

On Sunday, 31 July 2016 at 10:05:04 UTC, Basile B. wrote:

On Sunday, 31 July 2016 at 08:29:47 UTC, Basile B. wrote:

On Sunday, 31 July 2016 at 01:10:40 UTC, Thalamus wrote:

Any idea what I'm doing wrong?


Yes, what's going wrong is quite


actually you said that the LST is well generated but empty so 
my previous answer is  wrong, also i was focused on unittest 
coverage which doesn't seem to be what you want to verify.


Thank Basile. Yes, these aren't unit tests, but rather 
integration tests, end-to-end tests, etc., all of which are 
driven from external EXEs. This is a complex application 
consisting (thus far) of 17 D and C# projects. Within a single 
project, D (and Visual D) work very well, but across projects 
I've run into a lot of challenges. Not being able to build 
these projects into DLLs without resorting to C-linkage for 
D-to-D interop (which Benjamin Thaut is working on fixing) was 
tough to swallow, and I can't used LIBs because in some cases I 
have projects that are not referenced at build time but whose 
classes are instead discovered at run time, so I'm forced to 
resort to OBJs for now. Code coverage is a must, though, so I'm 
really digging in here.


I found part of the problem: Hitting F5 in Visual Studio after 
a fresh rebuild was giving me an error "cannot launch 
debugger... hr = 89710016" which looks to be related to Visual 
D. Subsequent runs work fine, but it was annoying me so I added 
the EXE itself as the startup project. This ran properly every 
time, but it resulted the LST files ending up in the build 
folder, and they were all empty. So I switched back to the test 
project as the startup project and, after the errant run, it 
generated LSTs in the EXE project root folder as expected. In 
this case, all the test EXE LST files were populated as 
expected, but all of the LSTs for the code being tested were 
still empty. I really don't need code coverage numbers for the 
test code, and currently I still get none for the code I do 
need to measure. But it's still progress.


If anyone else has ideas I'd love to hear them. Otherwise, if I 
figure it out, I will add a quick explanation to this thread.


thanks!


After a couple more hours today, I found a couple of solutions. 
Neither is satisfactory.


The first is to include the project that builds the EXE in the 
same folder as the project that builds the OBJ. The problem with 
this is that each OBJ will also have to have its own EXE, and 
aggregating information from each of these EXEs becomes a real 
chore.


The second is to include all the source files directly in the 
test EXE project, AND to move the test EXE into its own solution. 
Having to maintain the same module hierarchy in two projects is 
obviously error prone. Having to maintain the separate solution 
is not a problem, really, but the reason it's necessary is a bit 
annoying: it seems that Visual D automatically includes the OBJ 
for any project previously built in the build process of 
subsequent projects, so whether you build the test EXE first or 
last, you end up with multiple definition problems, once in the 
EXE and once in the project OBJ, or once in the project and once 
in the EXE's OBJ. Either way the build breaks.


If anyone has a third alternative, please let me know! Otherwise, 
I'll have to select the lesser of these two evils.


thanks!



Re: Empty LST files?

2016-07-31 Thread Thalamus via Digitalmars-d-learn

On Sunday, 31 July 2016 at 10:05:04 UTC, Basile B. wrote:

On Sunday, 31 July 2016 at 08:29:47 UTC, Basile B. wrote:

On Sunday, 31 July 2016 at 01:10:40 UTC, Thalamus wrote:

Any idea what I'm doing wrong?


Yes, what's going wrong is quite


actually you said that the LST is well generated but empty so 
my previous answer is  wrong, also i was focused on unittest 
coverage which doesn't seem to be what you want to verify.


Thank Basile. Yes, these aren't unit tests, but rather 
integration tests, end-to-end tests, etc., all of which are 
driven from external EXEs. This is a complex application 
consisting (thus far) of 17 D and C# projects. Within a single 
project, D (and Visual D) work very well, but across projects 
I've run into a lot of challenges. Not being able to build these 
projects into DLLs without resorting to C-linkage for D-to-D 
interop (which Benjamin Thaut is working on fixing) was tough to 
swallow, and I can't used LIBs because in some cases I have 
projects that are not referenced at build time but whose classes 
are instead discovered at run time, so I'm forced to resort to 
OBJs for now. Code coverage is a must, though, so I'm really 
digging in here.


I found part of the problem: Hitting F5 in Visual Studio after a 
fresh rebuild was giving me an error "cannot launch debugger... 
hr = 89710016" which looks to be related to Visual D. Subsequent 
runs work fine, but it was annoying me so I added the EXE itself 
as the startup project. This ran properly every time, but it 
resulted the LST files ending up in the build folder, and they 
were all empty. So I switched back to the test project as the 
startup project and, after the errant run, it generated LSTs in 
the EXE project root folder as expected. In this case, all the 
test EXE LST files were populated as expected, but all of the 
LSTs for the code being tested were still empty. I really don't 
need code coverage numbers for the test code, and currently I 
still get none for the code I do need to measure. But it's still 
progress.


If anyone else has ideas I'd love to hear them. Otherwise, if I 
figure it out, I will add a quick explanation to this thread.


thanks!


Empty LST files?

2016-07-30 Thread Thalamus via Digitalmars-d-learn
I'm running into a problem where when I specify -cov in the DMD 
compiler command, the coverage LST files are generated, but 
they're all empty. Has anyone else run into this before? My 
command line is:


dmd -m64 -gc -debug -w -wi -cov -X -Xf"obj\Unit.json" -I\ 
-deps="obj\Unit.dep" -c -odobj\Unit.build.rsp Interfaces.obj 
Invokers.obj (plus a whole lot of other .objs)


This is for a test EXE. I thought there may be some trouble when 
generating files for the .d from the .obj files, but even the .d 
files local to the test EXE end up with empty LST files.


Any idea what I'm doing wrong?

thanks!



Re: Registration-free COM client

2016-06-29 Thread Thalamus via Digitalmars-d-learn

On Wednesday, 29 June 2016 at 19:21:50 UTC, John wrote:

On Wednesday, 29 June 2016 at 14:51:10 UTC, Thalamus wrote:

[...]


A little research reveals that C# COM servers don't export 
DllGetClassObject, or any of the COM server plumbing. 
"Registering for COM interop" merely adds the registry entries 
- which is the step you're trying to avoid by loading the DLL 
dynamically. Then you'd run regasm on it to generate a type 
library. 
https://msdn.microsoft.com/en-us/library/aa645738(v=vs.71).aspx


Thanks John! Yes, I did forget to add : IUnknown. I would have 
caught that, but I appreciate you pointing that out. Thanks also 
for the link to the regasm article.


Re: Registration-free COM client

2016-06-29 Thread Thalamus via Digitalmars-d-learn

On Tuesday, 28 June 2016 at 02:30:56 UTC, thedeemon wrote:
To load load a COM object from a given file (DLL or AX) without 
having it registered, just load the file with CoLoadLibrary() 
and use its DllGetClassObject() function to get IClassFactory 
which will give you any kind of object in this library.
Here's how I do it (in my case the requested object has 
"IBaseFilter" COM interface):


Thanks to both of you!

I was hoping there would be a code-only solution, and I'm glad to 
see one is possible. It isn't quite working for me yet, though. I 
can get the HINSTANCE in the CoLoadLibrary call, but 
GetProcAddress for DllGetClassObject fails, with 
ERROR_PROC_NOT_FOUND.


I've never written a COM server before (only clients), so I must 
be building the C# assembly incorrectly. I'm just not sure how. 
Everything across the board is built as 64-bit, and I've selected 
"Register for COM interop". The C# is pretty simple:


[ComVisible(true)]
[Guid("B99B6E64-966C-4655-B633-D0108F4DE909")]
public interface ITestInterface
{
int Identifier();
}

[ComVisible(true)]
[Guid("0F8BDA67-D6CF-42D0-A62D-E19BD7864362")]
[ClassInterface(ClassInterfaceType.None)]
public class TestClass : ITestInterface
{
public int Identifier()
{
return 42;
}
}

and the D code (mostly unchanged from your example):

interface ITestInterface
{
int Identifier();
}


ITestInterface GetInstance()
{
import std.exception;
import core.sys.windows.com;
GUID iid = { 0xB99B6E64, 0x966C, 0x4655, [0xB6, 0x33, 0xD0, 
0x10, 0x8F, 0x4D, 0xE9, 0x09]};
GUID clsid = { 0x0F8BDA67, 0xD6CF, 0x42D0, [0xA6, 0x2D, 0xE1, 
0x9B, 0xD7, 0x86, 0x43, 0x62]};


HINSTANCE hinst = 
CoLoadLibrary(cast(wchar*)r"managed\bin\test.dll".toUTF16z, 0); 
//CoFreeLibrary will need to be called later.

enforce!COMException(hinst);

LPFNGETCLASSOBJECT fnGetClassObject = 
cast(LPFNGETCLASSOBJECT)GetProcAddress(hinst, 
"DllGetClassObject");

enforce!COMException(fnGetClassObject);

IClassFactory factory;
auto factory_iid = IID_IClassFactory;
fnGetClassObject(, _iid, 
cast(void**)).checkHR("fnGetClassObject failed");

enforce!COMException(factory);

ITestInterface instance;
factory.CreateInstance(null, , 
cast(void**)).checkHR("factory.CreateInstance");

return instance;
}

Any ideas what I'm missing?

thanks!
Gene


Registration-free COM client

2016-06-27 Thread Thalamus via Digitalmars-d-learn

Hi everyone,

I've succeeded in using D as a client for regular (registered) 
COM servers in the past, but in this case, I'm building the 
server as well. I would like to avoid registering it if possible 
so XCOPY-like deployment remains an option. Can a 
registration-free COM client be built in D? If so, how can the 
code be setup to consume the manifest file, or alternately, is 
there a way to just point D to the correct assembly directly in 
code?


Some background info:

The project I'm working on requires a high degree of D and C# 
interop. Getting C# to invoke D via C linkage is simple, but I've 
encountered a lot of problems the other way around.


Although it's technically possible to get pointers to C# objects 
such that the same approach could be used, doing so would require 
large portions of the code to be marked unsafe, the objects to be 
instantiated as fixed, use of GCHandle.Alloc, etc., which has a 
high dev learning curve and scalability issues.


The typical solution is to use delegates as callbacks. This 
works, but it doesn't scale well to more complex scenarios. You 
can send a struct of delegates to the D layer and use that to 
access public methods in a class, but if one of those methods 
would normally return a instance of a different class and the 
caller will need to invoke methods within that other class, this 
approach breaks down. For example, 
MyClassInstance.MyProperty.DoSomething() can't be modeled as 
MyClassInstanceDelegate.MyPropertyDelegate.DoSomethingDelegate(). 
This fails marshaling, because delegates are not blittable. 
There's very likely a way to structure complex delegate 
hierarchies that would in the end be marshalable, but the 
implementation and maintenance overhead would be sizable.


This leaves COM, which seems like it would work fine, on Windows 
anyway. (I'm not sure about Linux, but maybe some combo of Mono 
and WINE would do it? Not a high prio right now.) I'm hoping, 
though, to avoid having to register the C# COM server to keep 
things as simple as possible.


thanks!


Re: TypeInfo_Interface from runtime string?

2016-06-22 Thread Thalamus via Digitalmars-d-learn

On Wednesday, 22 June 2016 at 15:46:15 UTC, Thalamus wrote:

On Wednesday, 22 June 2016 at 15:43:08 UTC, Basile B. wrote:

On Wednesday, 22 June 2016 at 15:15:51 UTC, Thalamus wrote:

[...]


No need for a constructor. typeid() returns a static instance 
that's pre-allocated.


[...]


Thanks Basile.


Hit Send too soon...

Thanks Basile. As it turned out I was already doing something 
very similar for mapping types to interfaces and to other types, 
using shared static constructors to perform registration into 
associative arrays, e.g.


TypeInfo_Class[TypeInfo_Class]
 and
TypeInfo_Interface[TypeInfo_Class]

So I can easily add

TypeInfo_Interface[string]
 and
TypeInfo_Class[string]

as part of the existing registration process and then expose a 
simple lookup method. Thanks for the good idea! :)






Re: TypeInfo_Interface from runtime string?

2016-06-22 Thread Thalamus via Digitalmars-d-learn

On Wednesday, 22 June 2016 at 15:43:08 UTC, Basile B. wrote:

On Wednesday, 22 June 2016 at 15:15:51 UTC, Thalamus wrote:

[...]


No need for a constructor. typeid() returns a static instance 
that's pre-allocated.


[...]


Thanks Basile.


TypeInfo_Interface from runtime string?

2016-06-22 Thread Thalamus via Digitalmars-d-learn

Hi everyone,

My project includes lots of .Net interop via C linkage. One of 
the things I need to do is refer in C# to an interface declared 
in the D code, and then to actually work with the interface 
concretely in the D layer. So, I need to get a TypeInfo_Interface 
object from a string passed in from C#.


The problem isn't in marshaling the string between C# and D, but 
rather what to do with the string once I have it in D.


So in the D code, where interfaceName is the fully qualified name 
of an interface, e.g.  "MyPackage.MyModule.MyInterface", what I 
would like is something like:



TypeInfo_Interface theInterface = new 
TypeInfo_Interface(interfaceName);



But there's no such constructor.

Apologies if this seems like it should be obvious, but I couldn't 
find anything in the forums or the wider web. :)


thanks,
Thalamus



Re: Convert wchar* to wstring?

2016-04-05 Thread Thalamus via Digitalmars-d-learn

On Tuesday, 5 April 2016 at 19:19:10 UTC, ag0aep6g wrote:

On 05.04.2016 20:44, Thalamus wrote:

[...]


Aside: D has syntax for "// For wchar_t.": `import 
core.stdc.stddef: wchar_t;`.



[...]


wchar_t is not wchar. wstring is not (portably) compatible with 
a wchar_t array.


If you actually have a wchar_t* and you want a wstring as 
opposed to a wchar_t[], then you will potentially have to do 
some converting.


If you have a wchar*, then don't use wcslen, as that's defined 
in terms of wchar_t. There may be some function for finding the 
first null wchar from a wchar*, but I don't know it, and 
writing out a loop isn't exactly hard:



wstring toWstring(const(wchar)* value)
{
if (value is null) return null;
auto cursor = value;
while (*cursor != 0) ++cursor;
return value[0 .. cursor - value].dup;
}



Thank you for the feedback. You are correct.


Re: Convert wchar* to wstring?

2016-04-05 Thread Thalamus via Digitalmars-d-learn

On Tuesday, 5 April 2016 at 11:26:44 UTC, Thalamus wrote:

Thanks everyone! You've all been very helpful.


For anyone who has the same question and happens on this thread, 
I wanted to post what I finally came up with. I combined the 
information everyone in this thread gave me with what I saw in 
Phobos source for the to!string() implementation, closely 
following the latter. The important to!string() code is in the 
toImpl implementation in conv.d at line 880. The existing code 
uses strlen, but that's an ANSI function. Fortunately, D has 
wcslen available, too.


import core.stdc.stddef; // For wchar_t. This is defined 
differently for Windows vs POSIX.

import core.stdc.wchar_; // For wcslen.

wstring toWstring(wchar_t* value)
{
return value ? cast(wstring) value[0..wcslen(wstr)].dup : 
null;

}

The Phobos code notes that this operation is unsafe, because 
there's no guarantee the string is null-terminated as it should 
be. That's definitely true. The only outcome you can be really 
sure is accurate is an access violation. :)


thanks!
Thalamus



Re: Convert wchar* to wstring?

2016-04-05 Thread Thalamus via Digitalmars-d-learn

Thanks everyone! You've all been very helpful.




Re: Debugging D DLL from C# app with C linkage for native Unity 5 plugin

2016-03-30 Thread Thalamus via Digitalmars-d-learn

On Wednesday, 30 March 2016 at 07:38:07 UTC, Benjamin Thaut wrote:

On Tuesday, 29 March 2016 at 23:41:28 UTC, Thalamus wrote:


dmd  dllmain.d dll.def -w -wi 
-g -map -ofLogic.dll  
-m64 -debug -shared


Anyone know what I should try next? Am I missing something 
simple? :)


thanks!
Thalamus


You should be using "-gc" instead of "-g" when building 64-bit 
D programs that should be debugged with visual studio. 
Otherwise the visual studio debugger might get confused over 
some of the symbol names. (Because they contain '.')


Thanks Benjamin! I changed over to -gc.

I spent another couple of hours on this and finally figured it 
out. As it turns out, it wasn't necessary to change Just My Code. 
Enabling Mixed Mode debugging didn't work, but that's what set me 
down the path where I was able to find the answer.


Unity is an odd duck in a lot of ways. They use Mono to provide 
cross-platform portability, and that decision led them to use 
their own custom subset of .NET 3.5. Although I had eliminated 
Unity and Mono from the repro, I had accidentally left that 
subset on the C# EXE.


Because of this, VS uses a different managed code debugger (v3.5, 
v3.0, v2.0 instead of v4.6, v4.5, v4.0). This version doesn't 
play nicely with the Native debugger. By default, VS determines 
the debuggers to use automatically. So in this scenario, if you 
launch the EXE and then attach, it only loads the managed 
debugger (without telling you). If you select the old Managed and 
the Native debuggers in the Attach to Process dialog's Attach to: 
drop down list, an "Interop debugging is not supported" error 
pops up when you click Attach. (This is the same error you get if 
you select "Enable native code debugging" on the C# EXE's Debug 
property page.)


The solution is to select only Native or the older Managed 
debugger, but never both. That means that you can't hit F5 to 
launch the EXE in debug mode and then step through native code, 
which is inconvenient. But for my purposes debugging through 
Unity, attaching to an already running process is the only 
scenario I really need to work anyway. The C# layer is a very 
thin interop and marshaling layer between the C++ (hopefully soon 
D) core and Unity, so 99% of the time I'll need to debug only the 
native code anyway. The transition between the two is the only 
thing that can't be stepped through, and there isn't a whole lot 
to that.


As it turns out, I never saw this with the C++ version of the 
core logic because there were no C# projects in the solution, so 
VS automatically chose the Native one without my knowledge.


Hope this helps someone else in the future!

thanks,
Gene



Debugging D DLL from C# app with C linkage for native Unity 5 plugin

2016-03-29 Thread Thalamus via Digitalmars-d-learn
Apologies if this has been discussed before, but I wasn't able to 
find anything similar on the forums or web. I can't seem to 
figure out how to debug a D DLL from a C# EXE. (My actual purpose 
here is to use D to build native plugins for Unity 5, but Unity 
and Mono aren't necessary to repro the problem I'm running into.)


The D DLL and C# are both built as 64-bit. (C# is not set to 
AnyCPU). Using VS 2015 and Visual D, I can drive the D DLL from 
the C# EXE without any problems, but the debugger doesn't load 
the D DLL symbols. The DLL and PDB are in the same folder as the 
C# EXE. Everything behaves the same if I link to the DLL 
statically using P/Invoke or dynamically using LoadLibrary.


Everything from the D DLL is exposed as extern(C), listed in the 
.def, etc. When I drive the DLL from a D EXE, I can break into 
the debugger easily, whether I attach at launch or attach to the 
process when it's already running.


I'm building the DLL using:

dmd  dllmain.d dll.def -w -wi -g 
-map -ofLogic.dll  -m64 
-debug -shared


Anyone know what I should try next? Am I missing something 
simple? :)


thanks!
Thalamus




Re: Shared static constructors from C# EXE

2016-02-26 Thread Thalamus via Digitalmars-d-learn

On Friday, 26 February 2016 at 08:37:35 UTC, Benjamin Thaut wrote:

On Thursday, 25 February 2016 at 17:46:18 UTC, Thalamus wrote:
On Thursday, 25 February 2016 at 16:05:37 UTC, Benjamin Thaut 
wrote:

[...]


Thanks Benjamin. When I went to whittle this down to its 
barest essentials, though, the repro is pretty simple. It 
involves LIBs, but not Dlls, and it doesn't require anything 
but a single D EXE.


[...]


The problem is that when you build with -lib the resulting 
library is optimized for linker stripping. E.g. everything that 
is not directly used will not be pulled into the final 
executable. If you want everything in the final exectuable you 
shouldn't be using a .lib file. Instead compile with -c 
resutling in a .obj file and link the resulting .obj file into 
your executable. Then everything will end up in the final 
executable even if its not directly used.


Kind Regards
Benjamin Thaut


Thanks Benjamin! I knew there had to be some simple thing I 
didn't know I needed to do here. It worked like a charm in the 
simple repro. In my actual code, I'm running into _deh_beg 
already defined and a few more linker errors, but I haven't had 
the chance to delve there yet.


thanks again!



Re: Shared static constructors from C# EXE

2016-02-25 Thread Thalamus via Digitalmars-d-learn
On Thursday, 25 February 2016 at 16:05:37 UTC, Benjamin Thaut 
wrote:

On Thursday, 25 February 2016 at 14:42:14 UTC, Thalamus wrote:

your entry point.


Hi Guillaume,

Thanks for responding so quickly! I had found that wiki page 
before and I'd been following the "DLLs with a C Interface" 
section closely. I had forgotten to add -shared when building 
the DLL, but the behavior didn't change when I added it. So, I 
added a call to Runtime.initialize() as the first line of the 
endpoint I'm exposing. (I also made sure that this was the 
only endpoint invoked and that it was only invoked once just 
to be cautious.) I can see Runtime.initialize() being called, 
but the Class A shared static constructor still is not called 
when run from the C# EXE.


Do you have any other ideas?

In the meantime, I'm working on putting together a minimal 
repro source, but the scenario is a bit complicated so there's 
a lot of details to whittle away.


thanks!
Gene


You shouldn't be calling Runtime.initialize() manually. Just do 
the following in one of your source files:


import core.sys.windows.dll;
mixin SimpleDllMain;

This will generate a DllMain that will correctly initialize and 
deinitialize druntime.


Kind Regards
Benjamin Thaut


Thanks Benjamin. When I went to whittle this down to its barest 
essentials, though, the repro is pretty simple. It involves LIBs, 
but not Dlls, and it doesn't require anything but a single D EXE.


NOTE: if attempting to repro any of this, you must do a clean 
build after changing build.cmd or main.d before you'll see a 
change in behavior. I have the shared static ctors output files 
to make it really easy to see.


If you have Class A:

module ClassA;

import std.file;
import std.stdio;

export class ClassA
{
shared static this()
{
File file = File(r"c:\A.txt", "w");
file.writeln("Called A's shared static constructor."); 
file.flush();

file.close();
}
}

and you have Class B:

module ClassB;

import std.file;
import std.stdio;

export class ClassB
{
shared static this()
{
File file = File(r"c:\B.txt", "w");
file.writeln("Called B's shared static constructor."); 
file.flush();

file.close();
}
}

and you have main.d:

void main()
{
}

And you build it in one step into an EXE:

dmd -m64 -debug ClassA.d ClassB.d main.d -ofDriver.exe

Then you run Driver.exe, both A.txt and B.txt are created.

But, if you build it as a LIB and then link the LIB to the EXE:

dmd -c -lib -m64 -debug ClassA.d ClassB.d -ofInit.lib
dmd -m64 -debug Init.lib main.d -ofDriver.exe

When you run Driver.exe, neither are created. If you then add 
"import ClassA" to main.d and clean build, only A.txt will be 
created, or instead if you add "import ClassB", then only B.txt 
is created. Also, if either of these is included, Driver.exp and 
Driver.lib are emitted by the build, whereas otherwise they 
aren't.


It looks from this like a class in a linked LIB that is not 
directly imported will not have its shared static constructor 
called. Am I missing something obvious? :)


Long term I will need all this not only in separate LIBs but in 
separate DLLs. My scenario is roughly like this (-> indicate 
dependencies):


ClassA : IClass -> ClassManagement
ClassB : IClass -> ClassManagement
EntryPoint -> ClassManagement, ClassB, IClass

Then EntryPoint asks ClassManagement to give it an instance of 
ClassB's complement (ClassA). ClassManagement only knows anything 
about any of these classes via TypeInfo_Class object mappings, 
and it uses Object.factory to instantiate them. EntryPoint and 
its dependencies then work with that object via the IClass 
interface. I've gotten this to work in C# easily and C++ with 
some effort. (Class map population was, of course, very different 
for each, though.)


I can probably figure out a way to make this work for now, but if 
there's a way to ensure shared static ctors are run in this 
scenario without importing modules across separation boundaries, 
it would be a very good thing.


thanks!
Gene




Re: Shared static constructors from C# EXE

2016-02-25 Thread Thalamus via Digitalmars-d-learn
On Thursday, 25 February 2016 at 14:07:21 UTC, Guillaume Piolat 
wrote:

On Thursday, 25 February 2016 at 14:01:30 UTC, Thalamus wrote:
I don't control the EXE itself and the code I write to 
interface with it must be either C# or JavaScript, but this 
repros with a test C# driver EXE as well. The interfacing C# 
code can only be aware of the exposed D DLL functions defined 
in .def and shouldn't be aware directly of Class A, B, or 
ClassMapper, the factory specifically, etc..




Make sure your DLL must initialize the D runtime, which is 
where shared static constructors should get called.


http://wiki.dlang.org/Win32_DLLs_in_D

Alternatively you can call Runtime.initialize() yourself in 
your entry point.


Hi Guillaume,

Thanks for responding so quickly! I had found that wiki page 
before and I'd been following the "DLLs with a C Interface" 
section closely. I had forgotten to add -shared when building the 
DLL, but the behavior didn't change when I added it. So, I added 
a call to Runtime.initialize() as the first line of the endpoint 
I'm exposing. (I also made sure that this was the only endpoint 
invoked and that it was only invoked once just to be cautious.) I 
can see Runtime.initialize() being called, but the Class A shared 
static constructor still is not called when run from the C# EXE.


Do you have any other ideas?

In the meantime, I'm working on putting together a minimal repro 
source, but the scenario is a bit complicated so there's a lot of 
details to whittle away.


thanks!
Gene



Shared static constructors from C# EXE

2016-02-25 Thread Thalamus via Digitalmars-d-learn

Hi everyone,

I looked in the forums and Google in general but I didn't find a 
similar question, and I'm stumped. I have a scenario where a set 
of classes must be registered with a class mapper and then 
instantiated via a factory. The classes themselves are agnostic 
of one another, and all interaction with these classes after 
instantiation is via interfaces. I've succeeded in having the 
classes register themselves at runtime by using shared static 
constructors, which is really seamless! This works just fine when 
the EXE is written in D, but only a subset of shared static 
constructors get called when the EXE is written in C#.


A few more details:

ClassMapper class includes a shared static constructor that 
initializes a class map associative array, and it exposes a 
public Map() function an Instantiate(TypeInfo_Class classType, 
etc.) function.
Class A and Class B both have shared static constructors that 
call Map() to register themselves.


The above is built into a D EXE, and ClassMapper.map is fully 
populated before main() starts.


-OR-

The above is built into a D DLL with a CreateClassB() function 
exposed via .def, etc. A C# EXE invokes CreateClassB() via 
p/invoke.


The call works just fine, and ClassB and anything class B calls, 
recursively, are all registered with ClassMapper.map just fine, 
because their shared static constructors are invoked. But, Class 
A is not in the map because its shared static constructor is 
never called.


I don't control the EXE itself and the code I write to interface 
with it must be either C# or JavaScript, but this repros with a 
test C# driver EXE as well. The interfacing C# code can only be 
aware of the exposed D DLL functions defined in .def and 
shouldn't be aware directly of Class A, B, or ClassMapper, the 
factory specifically, etc..


Has anyone seen this before, or have an idea for a workaround? 
The best workaround I've come up with so far is to use a registry 
config file instead of calls to Map() so the ClassMapper can 
populate itself. It's not a very elegant solution, but it was the 
best I was able to come up with for C++ too. (In C# I've used 
class attributes, which I had thought was elegant. D's shared 
static constructors are even more so, though.)


thanks much!
Thalamus


Re: Linking a DLL to a DLL with packages

2016-01-13 Thread Thalamus via Digitalmars-d-learn

On Sunday, 10 January 2016 at 15:58:55 UTC, Benjamin Thaut wrote:

Am 09.01.2016 um 16:45 schrieb Thalamus:


Hi Benjamin,

I wouldn't say I need DLLs to work fully _really_ badly. The 
only
non-negligible issue with single very large binaries that's 
crossed my
mind is patching, but we're years away from having to worry 
about that
too much. That being said, I'm definitely willing to do some 
testing,
especially for something that helps us down the road. I'll 
follow up

with you offline. Thanks!



Great, some help with bugfixing and testing would be greatly 
apreciated. I didn't get any e-mail from you yet, I assume you 
didn't send one?


Kind Regards
Benjamin Thaut


Hi Benjamin. Sorry for the delay. It's been a very busy week. I 
just hit Send on a mail to you.




Re: Linking a DLL to a DLL with packages

2016-01-09 Thread Thalamus via Digitalmars-d-learn

On Friday, 8 January 2016 at 12:13:15 UTC, Benjamin Thaut wrote:

On Thursday, 7 January 2016 at 19:29:43 UTC, Thalamus wrote:

Hi everyone,

First off, I've been working with D for a couple of weeks now 
and I think it's the bee's knees! :) Except for DLLs.


thanks! :)


Dlls don't currently work on Windows. The only thing that works 
is giving your dlls a C-like interface. If you need any kind of 
D interface (classes, modules, etc) it won't work. I'm 
currently working on this, if you need it really badly and are 
willing to help bug testing send me a mail to code at 
benjamin-thaut.de


Kind Regards
Benjamin Thaut


Hi Benjamin,

I wouldn't say I need DLLs to work fully _really_ badly. The only 
non-negligible issue with single very large binaries that's 
crossed my mind is patching, but we're years away from having to 
worry about that too much. That being said, I'm definitely 
willing to do some testing, especially for something that helps 
us down the road. I'll follow up with you offline. Thanks!




Linking a DLL to a DLL with packages

2016-01-07 Thread Thalamus via Digitalmars-d-learn

Hi everyone,

First off, I've been working with D for a couple of weeks now and 
I think it's the bee's knees! :) Except for DLLs.


I've been combing through forum posts and Google for this 
situation. Several threads and articles are close but don't quite 
cover what I'm doing here.


On Windows 10, using DMD, I'm creating (currently) six DLLs and 
several EXEs. Some of the DLLs and all of the EXEs are dependent 
on some subset of DLLs. Everything works great if, instead of 
DLLs, I just statically link everything, but that's not really 
what I want to do.


To boil it down, let's say I have a DLL called Extensions, which 
includes a package.d file for its modules with module name 
General. I can successfully build this DLL with the command line:


"dmd dllmain.d module1.d module2.d package.d othermodule.d 
extensions.def -ofExtensions.dll -g -map" and then "implib.exe 
/noi /system Extensions.lib Extensions.dll"


Then, I have a DLL called Platforms. Within is modulea which 
includes a module-scope "import Extensions.General" line. I build 
it with:


"dmd dllmain.d modulea.d moduleb.d package.d othermodulea.d 
platforms.def ..\Extensions\Extensions.lib -ofPlatforms.dll -g 
-map"


(I've tried varying these extensively, including -I paths, 
separating out the compile step from the linking step, and many 
other educated and desperate guesses, with no success.)


So I have a package.d in both DLLs. When I build Platforms, I get:
modulea.d(60): Error: module Extensions.General is in file 
'General.d' which cannot be read.


But of course there is no General.d because the package module 
has to be named package.d. I've tried changing the name and many, 
many other things, but no dice.


Does anyone have other ideas? I'd really rather avoid a single 
giant EXE at the end, if I can.


thanks! :)