PC Review


Reply
Thread Tools Rate Thread

Create native DLL in c++ and call it from c#

 
 
pigeonrandle
Guest
Posts: n/a
 
      16th Jan 2007
Hi,
This is an answer, not a question. I hope it helps you since i was
messing around for ages trying to get information on this:

For anyone else wanting to create a test c++nativedll/c# project follow
these instructions...

1) Create a new 'Visual C++ - Win32 Console Project' - call it 'test'
1b) When the wizard pops up, click the 'Application Settings' link on
the left
1c) Select 'DLL' under 'Application Type'
1d) Click 'Finish' (don't worry, everything remains in English)

2) In test.cpp you will need to ADD the following code at the bottom of
the auto-generated stuff:

//START

struct MyTestStruct
{
int iSomeNumber;
int iAnotherNumber;
};

extern "C" __declspec(dllexport) void
DoSomethingWithStruct(MyTestStruct* mts);

void DoSomethingWithStruct(MyTestStruct* mts)
{
if (mts != NULL)
{
mts->iSomeNumber = 12345;
mts->iAnotherNumber = mts->iAnotherNumber + 67890;
}
}

//END

That's the dll sorted. As you can see, DoSomethingWithStruct just sets
the value of the referenced structure's members.

3) Now File > Add Project > New Project > 'Visual C# - Windows
Application'
3b) Add a button to your form - leave it named 'button1'
3c) Add the button click event handler
3d) Paste the code below OVER the entire event handler 'private void
button1_Click( ... ) { ... }':

//START

struct MyTestStruct
{
int iSomeNumber;
int iAnotherNumber;
};

[System.Runtime.InteropServices.DllImport(@"REPLACE
_THIS_WITH_THE_PATH_TO_YOUR_TEST.DLL_FILE\test\Deb ug\test.dll")]
private static extern void DoSomethingWithStruct(ref MyTestStruct
theStruct);

private void button1_Click(object sender, System.EventArgs e)
{
MyTestStruct mts = new MyTestStruct();
DoSomethingWithStruct(ref mts);
}

//END

3e) change the path where it says
REPLACE_THIS_WITH_THE_PATH_TO_YOUR_TEST.DLL_FILE to point to your dll.

4) Set the C# Windows Application as the startup project

5) Set a breakpoint so you can see that mts has indeed been changed

6) Run the project.

Shamelessly adapted from
http://blogs.msdn.com/jonathanswift/...02/780637.aspx, but
with some vital information added thanks to b0b - you know who you are.

Regards,
James Randle.

Also check out jonathan's followup article
http://blogs.msdn.com/jonathanswift/...23002900_.aspx
which eliminates the need to specify the location of the dll in the
DllImport attribute. Excellent work .

 
Reply With Quote
 
 
 
 
Michael C
Guest
Posts: n/a
 
      16th Jan 2007
"pigeonrandle" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> extern "C" __declspec(dllexport) void
> DoSomethingWithStruct(MyTestStruct* mts);


Doesn't this cause the name DoSomethingWithStruct to be mangled?

Michael


 
Reply With Quote
 
Ben Voigt
Guest
Posts: n/a
 
      16th Jan 2007

"Michael C" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "pigeonrandle" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> extern "C" __declspec(dllexport) void
>> DoSomethingWithStruct(MyTestStruct* mts);

>
> Doesn't this cause the name DoSomethingWithStruct to be mangled?


With extern "C", the compiler will just add a leading underscore. I think
P/Invoke is smart enough to find the export anyway. Other things it might
do is add "A" or "U" depending on whether you selected CharSet.Unicode or
not.

>
> Michael
>



 
Reply With Quote
 
pigeonrandle
Guest
Posts: n/a
 
      16th Jan 2007
Michael,

I don't think so (taken from
http://blogs.msdn.com/jonathanswift/...02/780637.aspx)...

Using extern "C" forces the compiler to use the actual function name
(as it would in C). This prevents us from overloading this function but
we're not bothered about that in this example.
On a related note, if you want to examine a dll to find out, amongst
other things, exported function names, you can use the dumpbin command
from the Visual Studio command prompt. Typing dumpin /exports filename
will list the exported function names from the dll. Try it on our
simple dll with and without the extern "C" keywords to see the
decoration in action.

....unless you have something you'd like to add?!

Cheers,
James.

Again, maximum respect to Jonathan Swift, whoever you are

Michael C wrote:
> "pigeonrandle" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > extern "C" __declspec(dllexport) void
> > DoSomethingWithStruct(MyTestStruct* mts);

>
> Doesn't this cause the name DoSomethingWithStruct to be mangled?
>
> Michael


 
Reply With Quote
 
Mattias Sjögren
Guest
Posts: n/a
 
      16th Jan 2007

>Using extern "C" forces the compiler to use the actual function name
>(as it would in C).


Because you're using the cdecl calling convention. If you want to keep
it that way and not switch to stdcall (which is more common for Win32
APIs), you should specify that in your DllImport attribute.


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
 
Reply With Quote
 
Michael C
Guest
Posts: n/a
 
      17th Jan 2007
"Mattias Sjögren" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
>>Using extern "C" forces the compiler to use the actual function name
>>(as it would in C).

>
> Because you're using the cdecl calling convention. If you want to keep
> it that way and not switch to stdcall (which is more common for Win32
> APIs), you should specify that in your DllImport attribute.


So to use stdcall you need a DEF file?

Michael


 
Reply With Quote
 
Michael C
Guest
Posts: n/a
 
      17th Jan 2007
"Mattias Sjögren" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
>>Using extern "C" forces the compiler to use the actual function name
>>(as it would in C).

>
> Because you're using the cdecl calling convention. If you want to keep
> it that way and not switch to stdcall (which is more common for Win32
> APIs), you should specify that in your DllImport attribute.


It's interesting that this example worked at all. C is using cdecl while c#
is using stdcall.

Michael


 
Reply With Quote
 
Mattias Sjögren
Guest
Posts: n/a
 
      17th Jan 2007
>So to use stdcall you need a DEF file?

To get it exported with an unmangled name, yes.

To be able to call it from .NET, no. The stdcall naming scheme is

_<function name>@<parameter byte count>

and like Ben mentioned, .NET can and will try that if the function
isn't found by its unmangled name.


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
 
Reply With Quote
 
pigeonrandle
Guest
Posts: n/a
 
      17th Jan 2007
All,
Perhaps one of you would like to modify the example I posted to reflect
what you have said? The reason i posted this in the first place was to
give people a starting point that was free from confusion!

Cheers,
James.


Mattias Sjögren wrote:
> >So to use stdcall you need a DEF file?

>
> To get it exported with an unmangled name, yes.
>
> To be able to call it from .NET, no. The stdcall naming scheme is
>
> _<function name>@<parameter byte count>
>
> and like Ben mentioned, .NET can and will try that if the function
> isn't found by its unmangled name.
>
>
> Mattias
>
> --
> Mattias Sjögren [C# MVP] mattias @ mvps.org
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.


 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      17th Jan 2007
"Michael C" <(E-Mail Removed)> wrote in message
news:%23W$(E-Mail Removed)...
> "Mattias Sjögren" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>>
>>>Using extern "C" forces the compiler to use the actual function name
>>>(as it would in C).

>>
>> Because you're using the cdecl calling convention. If you want to keep
>> it that way and not switch to stdcall (which is more common for Win32
>> APIs), you should specify that in your DllImport attribute.

>
> It's interesting that this example worked at all. C is using cdecl while c# is using
> stdcall.
>
> Michael
>


Yep, this results in a corrupted stack, but you don't call C directly from C#, the PInvoke
interop layer fixes the calling convention mismatch.
Anyway, this is a bug that should be corrected by the author of the code, you should not
rely on the CLR to do the right thing.

Willy.


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can P/Invoke call a native method of a native class? blackbiscuit Microsoft C# .NET 9 4th Jun 2009 11:31 AM
Can P/Invoke call a native method of a native class? blackbiscuit Microsoft C# .NET 0 11th May 2009 02:04 PM
Native C DLL Call. Sudeep Microsoft C# .NET 1 11th Jan 2009 11:45 AM
Re: how to call CLI code from native C++ Ben Voigt Microsoft VC .NET 0 9th Jan 2007 07:24 PM
.net dll call from native c++ sunil s via DotNetMonster.com Microsoft Dot NET 1 12th Jun 2005 08:56 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 12:06 AM.