View mode: basic / threaded / horizontal-split · Log in · Help
September 28, 2005
Access Violation calling a D DLL from a C# DLL
I'm getting an access violation when calling into a D DLL from C#.

A bit of background:  I'm writing a chess AI in D for a school project.  It has
to interface with a C# application, in VS 2005 Beta 2.  The C# application
dynamically loads a C# DLL, which is a thin wrapper for my D DLL.  This wrapper
uses C#'s interop services to load my D DLL and make calls to it.  The call I'm
making which is crashing is (in the C# code):

[DllImport("chess.dll")]
private static extern ChessMove getNextMove(ChessMove opponentsMove);

On the D side, the method looks like:

export extern(C) ChessMove getNextMove(ChessMove opponentsMove){..}

ChessMove is a struct defined in C# and D, which I've carefully verified to have
the same size and member offsets.

getNextMove() does a best-move search as deep as it can, time-limited to 5
seconds, after which it returns.  The odd thing is, if I limit it to only run a
couple of levels deep of search, it returns fine--no access violation.  However,
if I search to the full 5-second time limit, I get an AccessViolationException
in C#.

I've tested the code separately in a plain D program, and it runs fine, no
errors, for the full 5 seconds per move.  It's only when I call it through C#
that it causes the error.

I suspected the garbage collector, so I tried calling disable() as soon as I
enter getNextMove(), and never calling enable(), just to test.  However, the
access violation still occurs.

I've searched in this group and on the Internet for reasons this might be
happening, and haven't found any answers.  Just wanted to see if you folks had
any ideas.  I'd hate to have to port to C# ;)
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
David Gileadi <david et solutionstream com> wrote:
> I'm getting an access violation when calling into a D DLL from C#.
> 
> A bit of background:  I'm writing a chess AI in D for a school project.  It has
> to interface with a C# application, in VS 2005 Beta 2.  The C# application
> dynamically loads a C# DLL, which is a thin wrapper for my D DLL.  This wrapper
> uses C#'s interop services to load my D DLL and make calls to it.  The call I'm
> making which is crashing is (in the C# code):
> 
> [DllImport("chess.dll")]
> private static extern ChessMove getNextMove(ChessMove opponentsMove);
> 
> On the D side, the method looks like:
> 
> export extern(C) ChessMove getNextMove(ChessMove opponentsMove){..}
> 
> ChessMove is a struct defined in C# and D, which I've carefully verified to have
> the same size and member offsets.
> 
> getNextMove() does a best-move search as deep as it can, time-limited to 5
> seconds, after which it returns.  The odd thing is, if I limit it to only run a
> couple of levels deep of search, it returns fine--no access violation.  However,
> if I search to the full 5-second time limit, I get an AccessViolationException
> in C#.
> 
> I've tested the code separately in a plain D program, and it runs fine, no
> errors, for the full 5 seconds per move.  It's only when I call it through C#
> that it causes the error.
> 
> I suspected the garbage collector, so I tried calling disable() as soon as I
> enter getNextMove(), and never calling enable(), just to test.  However, the
> access violation still occurs.
> 
> I've searched in this group and on the Internet for reasons this might be
> happening, and haven't found any answers.  Just wanted to see if you folks had
> any ideas.  I'd hate to have to port to C# ;)
> 
> 

I don't think you're going to get anywhere attempting to make C# and D 
binary compatible.  They are completely different animals.  It's like 
trying to force a square peg into a round hole.

What you should do is take an intermediate step.  Since the only thing 
that is probably guaranteed to be portable between the two languages is 
a function calling convention, you might have to create "constructor" 
functions in both your C# and D code which take members from your 
ChessMove class as parameters and create the respective class in each 
language.  I'm not quite sure how to handle object references using this 
method, but I think you get the general idea.  This is basically a 
boiled down version of RPC (remote procedure call), except yours is 
local, so I'd say LPC =P.

Perhaps it is necessary for someone to write an interop library for D. 
Pardon my ignorance of existing D projects which already achieve this. 
Mango comes to mind as a candidate for this sort of thing being done 
already.  Anyone have such a library?  Speak up! =)

BTW, if you'd like me to elaborate more on this concept and do some 
testing, don't hesitate to ask.
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
In article <dheit4$95b$1@digitaldaemon.com>, James Dunne says...
>
>Perhaps it is necessary for someone to write an interop library for D. 
>Pardon my ignorance of existing D projects which already achieve this. 
>Mango comes to mind as a candidate for this sort of thing being done 
>already.  Anyone have such a library?  Speak up! =)

Someone was working on a way to compile D to IDL code, and things had gotten
pretty far last I heard.  But I'll be darned if I can remember who it was :p


Sean
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
Sean Kelly wrote:
> In article <dheit4$95b$1@digitaldaemon.com>, James Dunne says...
> 
>>Perhaps it is necessary for someone to write an interop library for D. 
>>Pardon my ignorance of existing D projects which already achieve this. 
>>Mango comes to mind as a candidate for this sort of thing being done 
>>already.  Anyone have such a library?  Speak up! =)
> 
> 
> Someone was working on a way to compile D to IDL code, and things had gotten
> pretty far last I heard.  But I'll be darned if I can remember who it was :p
> 
> 
> Sean
> 
> 

I'm not sure if compiling D code to MSIL is the best solution here, but 
we'd have to ask the OP what his reasons are for segregating the 
application between C# and D.
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
David Gileadi <david et solutionstream com> wrote:
> I'm getting an access violation when calling into a D DLL from C#.
> 
> A bit of background:  I'm writing a chess AI in D for a school project.  It has
> to interface with a C# application, in VS 2005 Beta 2.  The C# application
> dynamically loads a C# DLL, which is a thin wrapper for my D DLL.  This wrapper
> uses C#'s interop services to load my D DLL and make calls to it.  The call I'm
> making which is crashing is (in the C# code):
> 
> [DllImport("chess.dll")]
> private static extern ChessMove getNextMove(ChessMove opponentsMove);
> 
> On the D side, the method looks like:
> 
> export extern(C) ChessMove getNextMove(ChessMove opponentsMove){..}

I suspect the calling convention between C# and D doesn't match. By 
default, C# assumes _stdcall. But I see you've declared the D side as 
extern(C).
You can try specifing on the C# side
[DllImport("chess.dll",CallingConvention=CallingConvention.Cdecl)]
Or you could modify the D syntax, but I'm unfamiliar with how that works 
in D.
Hope that helps.

-- 
Joel Lucsy
"The dinosaurs became extinct because they didn't have a space program." 
-- Larry Niven
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
In article <dheit4$95b$1@digitaldaemon.com>, James Dunne says...
>
>David Gileadi <david et solutionstream com> wrote:
>> I'm getting an access violation when calling into a D DLL from C#.
>> 
>> A bit of background:  I'm writing a chess AI in D for a school project.  It has
>> to interface with a C# application, in VS 2005 Beta 2.  The C# application
>> dynamically loads a C# DLL, which is a thin wrapper for my D DLL.  This wrapper
>> uses C#'s interop services to load my D DLL and make calls to it.  The call I'm
>> making which is crashing is (in the C# code):
>> 
>> [DllImport("chess.dll")]
>> private static extern ChessMove getNextMove(ChessMove opponentsMove);
>> 
>> On the D side, the method looks like:
>> 
>> export extern(C) ChessMove getNextMove(ChessMove opponentsMove){..}
>> 
>> ChessMove is a struct defined in C# and D, which I've carefully verified to have
>> the same size and member offsets.
>> 
>> getNextMove() does a best-move search as deep as it can, time-limited to 5
>> seconds, after which it returns.  The odd thing is, if I limit it to only run a
>> couple of levels deep of search, it returns fine--no access violation.  However,
>> if I search to the full 5-second time limit, I get an AccessViolationException
>> in C#.
>> 
>> I've tested the code separately in a plain D program, and it runs fine, no
>> errors, for the full 5 seconds per move.  It's only when I call it through C#
>> that it causes the error.
>> 
>> I suspected the garbage collector, so I tried calling disable() as soon as I
>> enter getNextMove(), and never calling enable(), just to test.  However, the
>> access violation still occurs.
>> 
>> I've searched in this group and on the Internet for reasons this might be
>> happening, and haven't found any answers.  Just wanted to see if you folks had
>> any ideas.  I'd hate to have to port to C# ;)
>> 
>> 
>
>I don't think you're going to get anywhere attempting to make C# and D 
>binary compatible.  They are completely different animals.  It's like 
>trying to force a square peg into a round hole.
>
>What you should do is take an intermediate step.  Since the only thing 
>that is probably guaranteed to be portable between the two languages is 
>a function calling convention, you might have to create "constructor" 
>functions in both your C# and D code which take members from your 
>ChessMove class as parameters and create the respective class in each 
>language.  I'm not quite sure how to handle object references using this 
>method, but I think you get the general idea.  This is basically a 
>boiled down version of RPC (remote procedure call), except yours is 
>local, so I'd say LPC =P.
>
>Perhaps it is necessary for someone to write an interop library for D. 
>Pardon my ignorance of existing D projects which already achieve this. 
>Mango comes to mind as a candidate for this sort of thing being done 
>already.  Anyone have such a library?  Speak up! =)
>
>BTW, if you'd like me to elaborate more on this concept and do some 
>testing, don't hesitate to ask.

Thanks for your reply.

Well, my hope (and belief from the D docs) was that D structs are also C binary
compatible, as they are in C#, with some tweaking.  ChessMove is a fairly simple
struct, with 3 enums and 5 ints.  I tested passing it from C# as an argument,
accessing its members and passing back another, and verified that the values
were passed correctly both ways.  None of this resulted in an access violation.
It's only when my code runs for a while, presumably also using more memory, that
I get the access violation.

So in short, I'd hoped for C binary compatibility, and it's seemed to work as
far as that goes.  My worry is that somehow a garbage collector is trying to
overstep its bounds, or some other strange thing is afoot.
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
David Gileadi <david et solutionstream com> schrieb:

> Well, my hope (and belief from the D docs) was that D structs are also C binary
> compatible, as they are in C#, with some tweaking.  ChessMove is a fairly simple
> struct, with 3 enums and 5 ints.  I tested passing it from C# as an argument,
> accessing its members and passing back another, and verified that the values
> were passed correctly both ways.  None of this resulted in an access violation.
> It's only when my code runs for a while, presumably also using more memory, that
> I get the access violation.
> 
> So in short, I'd hoped for C binary compatibility, and it's seemed to work as
> far as that goes.  My worry is that somehow a garbage collector is trying to
> overstep its bounds, or some other strange thing is afoot.

Do you check in D that the to-be-returned struct exists at the expected
location and is "sane" before actually returning it?

What happen if you replace getNextMove with a dummy D function that
simply a) waits 5 seconds or b) loops (without any alarm/timer) for 5
seconds?

Thomas
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
In article <dhevd4$kr0$1@digitaldaemon.com>, =?UTF-8?B?VGhvbWFzIEvDvGhuZQ==?=
says...
>
>-----BEGIN PGP SIGNED MESSAGE-----
>Hash: SHA1
>
>David Gileadi <david et solutionstream com> schrieb:
>
>> Well, my hope (and belief from the D docs) was that D structs are also C binary
>> compatible, as they are in C#, with some tweaking.  ChessMove is a fairly simple
>> struct, with 3 enums and 5 ints.  I tested passing it from C# as an argument,
>> accessing its members and passing back another, and verified that the values
>> were passed correctly both ways.  None of this resulted in an access violation.
>> It's only when my code runs for a while, presumably also using more memory, that
>> I get the access violation.
>> 
>> So in short, I'd hoped for C binary compatibility, and it's seemed to work as
>> far as that goes.  My worry is that somehow a garbage collector is trying to
>> overstep its bounds, or some other strange thing is afoot.
>
>Do you check in D that the to-be-returned struct exists at the expected
>location and is "sane" before actually returning it?
>
>What happen if you replace getNextMove with a dummy D function that
>simply a) waits 5 seconds or b) loops (without any alarm/timer) for 5
>seconds?
>
>Thomas
>-----BEGIN PGP SIGNATURE-----
>
>iD8DBQFDOwGY3w+/yD4P9tIRAlBGAKCILfmpCv5pT2vH8b+du16zLMWSFwCfVkDK
>Zov+Be5KRcjWofVyL5V4IRw=
>=jrEC
>-----END PGP SIGNATURE-----

Wow.  I wouldn't have expected it, but testing your dummy function theory a)
using the code

Thread.getThis().wait(5000);

and then returning a dummy ChessMove causes the access violation.  So it seems
that for whatever reason, the layer between the two sides can't handle the long
call.  Maybe it's C# trying to protect itself.  In any case, I can probably set
up some workaround using callbacks or some such.  Thanks for the help,

-Dave
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
In article <dhes7r$i5q$1@digitaldaemon.com>, David Gileadi <david et
solutionstream com> says...
>
> [snip]
>
>It's only when my code runs for a while, presumably also using more memory, that
>I get the access violation.

You mentioned that you're disabling the GC in the D-dll, is this still the case?
If so, then this is almost certainly the problem.

While disabling the GC side-steps any issues you may have with premature
collections from D's GC, you now have to adjust how you code your app.  In a
nutshell: virtually anything that would cause a leak in a C program now applies
to your D code, so you need to use 'delete' where appropriate to control memory
usage if you're not already.

There are also some D idoms that will consume additional memory without your
consent, and are beyond discrete control via 'delete'.  Array concatenations,
and other various uses of "Copy on Write" are the front-line offenders here. 

Also, there may be portions of Phobos (and any other external D libs for that
matter) that may not be "non-GC friendly" and assume a fully (or at least
periodically) garbage collected environment.  You may need to pair back your
dependencies to avoid any problems.

Otherwise, just stick with providing structs and other scalars/primitives
through your dll's interface, keep the GC on, and you should be okay.

- EricAnderton at yahoo
September 28, 2005
Re: Access Violation calling a D DLL from a C# DLL
In article <dhf29r$nmg$1@digitaldaemon.com>, pragma says...
>
>In article <dhes7r$i5q$1@digitaldaemon.com>, David Gileadi <david et
>solutionstream com> says...
>>
>> [snip]
>>
>>It's only when my code runs for a while, presumably also using more memory, that
>>I get the access violation.
>
>You mentioned that you're disabling the GC in the D-dll, is this still the case?
>If so, then this is almost certainly the problem.
>
>While disabling the GC side-steps any issues you may have with premature
>collections from D's GC, you now have to adjust how you code your app.  In a
>nutshell: virtually anything that would cause a leak in a C program now applies
>to your D code, so you need to use 'delete' where appropriate to control memory
>usage if you're not already.
>
>There are also some D idoms that will consume additional memory without your
>consent, and are beyond discrete control via 'delete'.  Array concatenations,
>and other various uses of "Copy on Write" are the front-line offenders here. 
>
>Also, there may be portions of Phobos (and any other external D libs for that
>matter) that may not be "non-GC friendly" and assume a fully (or at least
>periodically) garbage collected environment.  You may need to pair back your
>dependencies to avoid any problems.
>
>Otherwise, just stick with providing structs and other scalars/primitives
>through your dll's interface, keep the GC on, and you should be okay.
>
>- EricAnderton at yahoo

No, I wasn't brave enough to permanently disable the GC, just tried it to see if
it was the culprit (it didn't help the problem).  I quickly removed the disable
call.  GC in my opinion is one of the benefits of D.  I appreciate your advice
in any case.
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home