Compile Time Unmanaged DLL Checking
-
Does anyone know if it's possible to have VS .NET 2003 check the DLLImport functions at compile time? FOr instance
class PlatformInvokeTest { [DllImport("C_DLL.dll")] public static extern void BridgeFn(lo); public static void Main() { try { string lo = string.Empty; BridgeFn(lo); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } }
While in my DLL There is no BridgeFn function that takes a string. This generates an error only on execution. While not horrible on a small scale, on a larger scale things can get pretty hairy pretty quick. If there is no way to check this at compile time any workflow suggestions to make this easier? Thanks! -
Does anyone know if it's possible to have VS .NET 2003 check the DLLImport functions at compile time? FOr instance
class PlatformInvokeTest { [DllImport("C_DLL.dll")] public static extern void BridgeFn(lo); public static void Main() { try { string lo = string.Empty; BridgeFn(lo); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } }
While in my DLL There is no BridgeFn function that takes a string. This generates an error only on execution. While not horrible on a small scale, on a larger scale things can get pretty hairy pretty quick. If there is no way to check this at compile time any workflow suggestions to make this easier? Thanks!No, the compiler does not check these things (as you've found). Just make sure that the functions are exported from the DLL you're referencing. As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa. If you want to see what exports are available, I recommend using depends.exe (the Dependency Walker) from the Platform SDK (installed by default with VS.NET).
Microsoft MVP, Visual C# My Articles
-
No, the compiler does not check these things (as you've found). Just make sure that the functions are exported from the DLL you're referencing. As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa. If you want to see what exports are available, I recommend using depends.exe (the Dependency Walker) from the Platform SDK (installed by default with VS.NET).
Microsoft MVP, Visual C# My Articles
Heath Stewart wrote: As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa. Agreed, I don't know about you, but I have never written a program perfectly with out any mistakes before :-D I just wanted to avoid the case five months from now where I am trying to track down a bug and it turns out I was just passing the wrong data type in (Cause it seems like it doesn't do data type checking either) so guess that was my concern. We basiclly have DLLs that we want to tie into because C# has such and easy way to design interfaces and that stuff. We have a lot of DLL's so it will be done on a fairly large scale.
-
Heath Stewart wrote: As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa. Agreed, I don't know about you, but I have never written a program perfectly with out any mistakes before :-D I just wanted to avoid the case five months from now where I am trying to track down a bug and it turns out I was just passing the wrong data type in (Cause it seems like it doesn't do data type checking either) so guess that was my concern. We basiclly have DLLs that we want to tie into because C# has such and easy way to design interfaces and that stuff. We have a lot of DLL's so it will be done on a fairly large scale.
But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse. :) Data-type checking isn't supported because you're marshaling to an unmanaged platform. C/C++ doesn't perform any type checking, either, except for what the compiler can perform at compile-time. In an unmanaged world, arguments and return values are only pointers on the stack (most usually). There would be no way to determine this using a managed compiler. The best way to avoid errors is to truly understand the unmanaged and managed types, like that an unmanaged
int
is platform-dependent, i.e. 32 bits on a 32-bit processor and 64 bits on a 64-bit processor,thus you should use anIntPtr
. ALONG
is always 32 bits, hence is a managedInt32
(C#'sint
primitive). Achar*
is a managedstring
(noref
orout
) and should useCharSet.Ansi
, where anLPTSTR
is also astring
but should useCharSet.Auto
, etc. etc. One thing to note is that currently in the .NET FCL Microsoft usesint
where it should be anIntPtr
because .NET 1.x does not support the 64-bit platform (it will in 2.0). I suspect they will either change to usingIntPtr
internally or maintain two different builds specifying anint
for 32-bit platforms and along
for 64-bit platforms. I honestly don't know, but making your code use anIntPtr
now will ensure that when it is compiled for the 2.0 framework and run on a 32- or 64-bit platform that it will work correctly.Microsoft MVP, Visual C# My Articles
-
But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse. :) Data-type checking isn't supported because you're marshaling to an unmanaged platform. C/C++ doesn't perform any type checking, either, except for what the compiler can perform at compile-time. In an unmanaged world, arguments and return values are only pointers on the stack (most usually). There would be no way to determine this using a managed compiler. The best way to avoid errors is to truly understand the unmanaged and managed types, like that an unmanaged
int
is platform-dependent, i.e. 32 bits on a 32-bit processor and 64 bits on a 64-bit processor,thus you should use anIntPtr
. ALONG
is always 32 bits, hence is a managedInt32
(C#'sint
primitive). Achar*
is a managedstring
(noref
orout
) and should useCharSet.Ansi
, where anLPTSTR
is also astring
but should useCharSet.Auto
, etc. etc. One thing to note is that currently in the .NET FCL Microsoft usesint
where it should be anIntPtr
because .NET 1.x does not support the 64-bit platform (it will in 2.0). I suspect they will either change to usingIntPtr
internally or maintain two different builds specifying anint
for 32-bit platforms and along
for 64-bit platforms. I honestly don't know, but making your code use anIntPtr
now will ensure that when it is compiled for the 2.0 framework and run on a 32- or 64-bit platform that it will work correctly.Microsoft MVP, Visual C# My Articles
Heath Stewart wrote: But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse. So is there a way to do this in code? I am not the programmer writing the DLL's so while I'll try to keep my eye out the chances that something with the function (Data types etc) might change without me knowing right away.
-
Heath Stewart wrote: But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse. So is there a way to do this in code? I am not the programmer writing the DLL's so while I'll try to keep my eye out the chances that something with the function (Data types etc) might change without me knowing right away.
This is what internal processes are for. Some version control systems alert you of changes, such as the upcoming Microsoft Team System. If something changes, the compiler won't know - it's P/Invoking an unmanaged API so there is no type metadata, plain and simple.
Microsoft MVP, Visual C# My Articles