views:

71

answers:

2

What is the proper way to link to functions in a C# DLL from a C# application?

This is how my DLL looks:

namespace WMIQuery_Namespace
{
    public class WMIQuery
    {
        public static string GetPortName()
        {
            /* Does some stuff returning valid port name. */

            return string.Empty;
        }

        public static int ScanForAdapters()
        {
            /* Does some stuff returning valid adapter index. */

            return _index = -1;
        }
    }
}

This is how the interface in my application looks:

namespace MyApp_Namespace
{
    class MyApp_Class
    {
        internal static class WMIQuery
        {
            [DllImport("WMIQuery.dll")]
            internal static extern string GetPortName();

            [DllImport("WMIQuery.dll")]
            internal static extern int ScanForAdapters();
        }
    }
}

Everything compiles without any errors or warnings, but when I try to call these functions from my application this exception is thrown:

"Unable to find an entry point named 'ScanForAdapters' in DLL 'WMIQuery.dll'."

What am I doing wrong? I am aware that I can add WMIQuery as a reference, but I need to link it as an unmanaged DLL. Thanks.

+8  A: 

If the DLL is a C# DLL, you don't use P/Invoke to "link" to it.

Just add it as a reference to your project, and add, at the top of the class where you want to use it:

using WMIQuery_Namespace;

You can then directly do:

var port = WMIQuery.GetPortName();

No need for any code in the "client" side at all...


As for:

but the requirements of the application require that it be loaded dynamically at run-time. Thanks.

Realize that the assembly will not be loaded until the point in time that your application uses it. Assemblies in the CLR are not loaded at startup, but rather at the time the first type is used from within the assembly. There is no need to try to load it via P/Invoke in order to achieve late binding.

If you don't trust this, you can always use Assembly.Load and reflection to call the members, but Platform Invocation services will not work for loading a C# assembly.

Reed Copsey
Curious - why the downvoting? You can't P/Invoke a C# DLL...
Reed Copsey
I specifically mentioned in the question that the requirements of the application require that it be loaded dynamically at run-time; `WMIQuery` cannot be added as a reference, which is required to implement `using WMIQuery_Namespace`.
Jim Fell
@Jim: I just edited my answer to explain why...
Reed Copsey
@Jim: Assemblies are not loaded until the first type is actually used... adding a reference does not violate your requirements.
Reed Copsey
If a C++ application can link to a C# DLL, then it stands to reason that a C# application can link to a C# DLL as well, without being added as a reference to the project.
Jim Fell
@Jim: I also provided you with the only other real option here - P/Invoke will not work with a .NET assembly.
Reed Copsey
@Jim: A C++ application can't link to a C# dll - it can add it as a reference and use C++/CLI, or it can host the CLR, or it can use COM. It can't use LoadLibrary/FreeLibrary like a native DLL.
Reed Copsey
@Reed: Okay, so basically my problem is I get to write a couple DLLs that will need to interface to C# and C++ applications. I can add these DLLs (written in C# to save time) to the applicable C# application projects as a reference. Are you saying that the same C# DLLs can be added to the C++ projects as a reference as well?
Jim Fell
@Jim Fell: C++ can only load C# DLLs if it's managed C++ (that is, C++/CLI, running under the .NET Framework). The only way unmanaged C++ code can load classes from a C# DLL (i.e., a .NET Assembly) is to use COM interop and create COM instances. Then the COM interop infrastructure will load the .NET Framework. Basically, C# code is compiled to CLR bytecode, which cannot be executed without a running instance of the CLR; C++ compiled to native doesn't have a running instance of the CLR. To communicate between those two worlds you need to bridge that gap somehow.
Daniel Pryden
@Jim: Yes. If you use C++/CLI (turn on the /CLR flag), you can use .net assemblies directly within C++. The syntax is a bit different, though - so you'll need to get used to it, but it's fairly easy if you're familiar with C# and C++...
Reed Copsey
@Reed: Thanks for all the help. I've decided to backtrack and write my DLLs in unmanaged C++ to make life easier on myself in the long run.
Jim Fell
A: 

Hi Jim,

Does this satisfy your needs?

http://www.codeproject.com/KB/cs/csharpreflection.aspx

Chris

Chris