Jump to page: 1 2 3
Thread overview
Access Violation calling a D DLL from a C# DLL
Sep 28, 2005
David Gileadi
Sep 28, 2005
James Dunne
Sep 28, 2005
Sean Kelly
Sep 28, 2005
James Dunne
Sep 28, 2005
David Gileadi
Sep 28, 2005
Thomas Kühne
Sep 28, 2005
David Gileadi
Sep 28, 2005
Carlos Santander
Sep 28, 2005
Sean Kelly
Sep 28, 2005
Carlos Santander
Sep 28, 2005
David Gileadi
Sep 28, 2005
Carlos Santander
Sep 28, 2005
JT
Sep 29, 2005
Thomas Kühne
Sep 29, 2005
David Gileadi
GC.disable() has no effect?
Sep 30, 2005
David Gileadi
Sep 28, 2005
pragma
Sep 28, 2005
David Gileadi
Sep 29, 2005
James Dunne
Sep 28, 2005
Joel Lucsy
Sep 28, 2005
Niall FitzGibbon
September 28, 2005
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
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
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
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
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
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
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
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
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
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