Solved

Difference between the "Public Declare" and "DllImport" method of declaring a function in DLL

Posted on 2011-02-27
16
970 Views
Last Modified: 2012-05-11
Hello Experts -

What's the difference between the two?  I'm trying to write a DLL in VB.Net and I see both methods used when I do a search. Is it just matter of being more precise with no real functional disadvantages?
0
Comment
Question by:gbmcneil
  • 8
  • 7
16 Comments
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34994889
"Public Declare" is a left over from the VB6 days and is just there for to ease the transition for people moving to .Net. "DllImport" is the pure .Net method of importing.

However, both are only used for importing non-.Net DLL's into a project. So, if you are simply creating your own DLL then you won;t necessarily need either unless you are using an external DLL as part of your library.
0
 
LVL 10

Expert Comment

by:Asim Nazir
ID: 34995027
The Declare statement exposes a subset of the functionality of the DllImport attribute, and implies different marshaling behavior for parameters to make functions behave in a way familiar to VB6 developers.

Using a Declare statement gives you the same code as if the DllImport attribute is used with CallingConvention.Winapi, ExactSpelling=True and SetLastError=True. Adding an Alias clause has the same effect as using DllImport's EntryPoint property. Declare also supports using a Ansi/Auto/Unicode modifier that maps directly to the corresponding CharSet option. Using the Auto modifier also changes ExactSpelling to False.

String parameters gets special marshaling attributes when used in Declare statements. When passed ByVal, they are always treated as UnmanagedType.VBByRefStr, and the parameter is actually changed to be ByRef under the hood to enable changes to the string to be retrieved back. When declared as ByRef, the marshaling setting is one of UnmanagedType.AnsiBStr, UnmanagedType.TBStr or UnmanagedType.BStr, depending on which, if any, charset modifier is used. These implied marshaling settings can always be overridden by applying the MarshalAs attribute to the parameter. Return value Strings don't get any special marshaling set, neither does String arrays.

So Declare statements will do in most situations. The only time you really need to use the DllImport attribute on a regular Shared method is when you want to set the calling convention to something other than Winapi, set SetLastError=False or PreserveSig=False. Other than that, it's mostly a matter of personal preference.

Asim
0
 

Author Comment

by:gbmcneil
ID: 34999618
Gee. Thanks for responding to my question.

Maybe you could clarify something for me. Below are two ways of declaring the same API that I found on the web. One uses the DllImport method. The other does not.

You'll also note that one uses an "Alias" (the non-DllImport approach) and the other does not.

Questions:

1. I thought the API was "WritePrivateProfileStringA". If so, why doesn't the DllImport approach include an Alias - which I thought was the true name of the procedure?

2. Is this a mistake?

3. Can a DllImport declaration include an alias?

Thanks.





<DllImport("kernel32.dll", SetLastError:=True)> _
    Private Shared Function WritePrivateProfileString(ByVal
    lpAppName As String, _
                           ByVal lpKeyName As String, _
                           ByVal lpString As String, _
                           ByVal lpFileName As String) As Boolean
    End Function



    Public Declare Ansi Function WritePrivateProfileString _
    Lib "kernel32.dll" _
               Alias "WritePrivateProfileStringA" (ByVal _
               lpApplicationName As _
               String, ByVal lpKeyName As String,ByVal lpString _
               As String,ByVal lpFileName As String) As Integer

Open in new window

0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34999746
1) It isn't. The API function is called "WritePrivateProfileString". "WritePrivateProfileStringA" is the alias.
2) see 1#
3) No. DllImport doesn't support Alias
0
 

Author Comment

by:gbmcneil
ID: 34999870
I'm confused. Is the official Windows API "WritePrivateProfileString" or "WritePrivateProfileStringA"?
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 34999890
Sorry got that backwards. There are two API calls "WritePrivateProfileStringA" and "WritePrivateProfileStringW", one is ASCII (A) the other is UNICODE (W).

For the purposes of DllImport you specificy it as "WritePrivateProfileString". The CharSet option on the DllImport attribute controls which version is called.
0
 

Author Comment

by:gbmcneil
ID: 35000104
If the official Windiws API is "WritePrivateProfileStringA", then the DllImport method cited above is incorrect.

It should have been...

Private Shared Function WritePrivateProfieStringA.......

and, within my code, I would forever have to use the procedure called WritePrivateProfileStringA. Right?

With DllImport I have forfeited the option of referring to the function as just "WritePrivateProfileString". Which in turns tells me to stick with the conventional non-DllImport way of declaring this function (or procedure). Correct?
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 35000335
No. If you look at the first example in the following post:

     http://pinvoke.net/default.aspx/kernel32.WritePrivateProfileString

You will see that the DllImport method is declared as "WritePrivateProfileString" (i.e. as the alias). The "CharSet" option is set to "Unicode", which means that when you do the following in C#:

WritePrivateProfileString("Something", "SomeKey", "SomeValue", "SomeFile");

Open in new window

The CLR marshalling mechanism will actually make a call to the "real" WritePrivateProfileStringW() function of the API. If you set CharSet to ASCII then the CLR would marshall it as a call to WritePrivateProfileStringA()
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:gbmcneil
ID: 35000607
This would make a great Abbott and Costello routine.

Okay. How does the system know that, when the DllImport method is used, the user is requesting WritePrivateProfileStringA - when only the common usage terminology is provided?

That must mean there are "three" official Windows APIs for writing to an INI file -

WritePrivateProfileStringA
WritePrivateProfileStringW
WritePrivateProfileString

Note, that the VB.Net version of the declaration provided at the above web address says nothing about the Char Code being Unicode or Ansi.


0
 
LVL 52

Accepted Solution

by:
Carl Tawn earned 125 total points
ID: 35000663
>> Note, that the VB.Net version of the declaration provided at the above web address says nothing about the Char Code being Unicode or Ansi.
That's because CharSet is an optional parameter so the VB sample in that link uses the default. If it is omitted it defaults to Ansi (i kept calling it Ascii earlier, but it should have been Ansi)

The thing to remember is that you are not calling the API function directly. You are making a call to the CLR marshalling objects which translate your C# call into a API call. The marshalling mechanisms decides internally which version of the API call to make based on the parameters specified with the DllImport.

This is the documentation for the CharSet parameter which might make things a little clearer:

    http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.charset.aspx
0
 

Author Comment

by:gbmcneil
ID: 35000929
Okay. I think I get it now.

Finally, is it true that the declaration shown below is acceptable and would not be possible using the DllInput method?

Private Declare Ansi Function FlushPrivateProfileString _
      Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
      (ByVal lpApplicationName As Integer, _
      ByVal lpKeyName As Integer, ByVal lpString As Integer, _
      ByVal lpFileName As String) As Integer

Open in new window

0
 

Author Closing Comment

by:gbmcneil
ID: 35000954
You really worked for your pay on this one.

Unfortunately, I can't refer to one of your responses as comprising the answer. The answer is really a composite of everything you said.
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 35001142
This is untested, but the DllImport equivalent of what you posted should be something along the lines of:
    <DllImport("kernel32.dll", CharSet:=CharSet.Ansi, EntryPoint:="WritePrivateProfileString")> _
    Private Shared Function FlushPrivateProfileString(ByVal lpAppName As String, _
                        ByVal lpKeyName As String, _
                        ByVal lpString As String, _
                        ByVal lpFileName As String) As Boolean

Open in new window

0
 

Author Comment

by:gbmcneil
ID: 35001284
Carl -

I didn't know you could do that. So, which declaration method would you use?

If your declaration is workable, yet untested in all situations, may be the best approach would be to stick with tradition. That is, if there is no real advantage, why do it?
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 35001361
I generally code in C# so i'd use DllImport because it is the more .Net specific convention. The older VB6 syntax is there to ease the transition to .Net.

If you were planning to cross over between languages then the DllImport convention is a good habit to get into, but if you're not then there is no harm with sticking with what you know. At the end of the day both variations do precisely the same thing. As long as you're consistent in the method you use you should be ok.
0
 

Author Comment

by:gbmcneil
ID: 35001887
Thanks for all your help. You've been a real gentleman.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now