What is the Purpose of C# constructor extern modifier?
I know about usage of extern METHODS to invoke Win32 functions, but what about CONSTRUCTORS?
Please give the practical example.
Note this:
class MyClass
{
public extern MyClass();
}
I believe one use/purpose of an extern ctor is to have the constructor implemented within the CLR itself. if you disassemble mscorlib.dll using Reflector and look at the System.String type, you'll see:
[MethodImpl(MethodImplOptions.InternalCall)]
public extern String(char[] value);
Which basically tells us that the (char[]) ctor for the string class is externally implemented, as part of the .net runtime.
The c# spec here indicates that apart from private, internal, protected and public, extern may be used and that this is standard external reference - see here. This to me says that the contstructor is linked into the class at a later time. Just like the PInvoke calls are. There's nothing, I'm guessing, stopping the c# compiler implementer allowing linking of external .net .modules containing said external constructors.
I cannot give an example, but I suspect one way woud be to implement the constructor in MC++, or in fact just a simple IL .module.
Related
I have a couple of methods imported from a native .dll, using the following syntax:
internal static class DllClass {
[DllImport("Example.dll", EntryPoint = "ExampleFunction")]
public static extern int ExampleFunction([Out] ExampleStruct param);
}
Now, because I specified param as [Out], I would expect at least one of the following snippets to be valid:
ExampleStruct s;
DllCass.ExampleFunction(s);
ExampleStruct s;
DllCass.ExampleFunction([Out] s);
ExampleStruct s;
DllCass.ExampleFunction(out s);
However, none of them works. The only way I found to make it work was by initializing s.
ExampleStruct s = new ExampleStruct();
DllCass.ExampleFunction(s);
I have managed to fix that by rewriting the first snippet to the following code, but that feels kinda redundant.
internal static class DllClass {
[DllImport("Example.dll", EntryPoint = "ExampleFunction")]
public static extern int ExampleFunction([Out] out ExampleClass param);
}
I've read What's the difference between [Out] and out in C#? and because the accepted answer states that [Out] and out are equivalent in the context, it left me wondering why it didn't work for me and if my "solution" is appropriate.
Should I use both? Should I use only out? Should I use only [Out]?
The OutAttribute determines the runtime behavior of the parameter, but it has no impact at compile time. The out keyword is required if you want to use compile-time semantics.
Using just the out keyword will change the runtime marshaling, so the OutAttribute is optional. See this answer for more info.
Are you initializing it to a value inside the function? That's where the requirement comes in: out parameters must be assigned to at least once within the function which declares the parameter.
I have an unmanaged function call that is throwing this exception when I try to pass it the path to a file name.
I've read that this is likely caused by the DLL itself but I don't think that is the case since the DLL is used in another application, so the problem is likely in my method calling the function.
The specification:
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
Description:
p_instance the instance
path local filesystem path
And my method:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path")]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
I think I'm missing the convention call but what would that likely be? Or would it be something else causing this exception?
EDIT: Based on some comments I did some poking around and found... well, nothing. The struct for the instance is opaque, which means I have no idea in Laymans terms. My guess is that it means you don't need to reconstruct it in the application that is using it?
In a blind guess based on this, I replaced the return value that I had been using with the function responsible for setting the *p_instance value to a long instead of an IntPtr since when it was an IntPtr it was returning 0, and with a long I was seeing a value. Again, what an IntPtr is I don't really know. I was pretty happy to see something not 0 in the instance variable but when I ran it past that, it errored out again.
EDIT: I've expanded the question to here.
Based on the exception you're seeing and the declaration you've provided for the native function,
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
your p/invoke declaration is incorrect. You've mismatched the calling conventions. The default for the .NET p/invoke system is stdcall (to match the Windows API functions), but the default for C and C++ code is cdecl. You have to tell .NET explicitly that your function uses the cdecl calling convention.
So change it to look like this:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
Of course, I'm guessing that you're right about the return value being a pointer. The native function declaration you've shown is missing the return type.
As for your question about the instance parameter, and whether you are correctly using the IntPtr type: The parameter is a pointer to a libvlc_instance_t, so you have two basic ways of making that work using p/invoke. First is to declare the parameter as an IntPtr, which gets it marshalled like a raw pointer value. This is not particularly useful for cases where the pointer needs to be anything other than opaque (i.e. retrieved from one native function, stored, and then passed to another native function). Second is to declare a managed structure that mirrors the native structure, and then write the p/invoke declaration to use this structure so that the marshaller will handle things automatically. This is most useful if you actually need to interact with the values stored in the structure pointed to by the pointer.
In this case, after a Google search, it looks like you're using one of the VLC APIs. Specifically this one. That also tells us what an libvlc_instance_t is: it is an opaque structure that represents a libvlc instance. So declaring a managed structure is not an option here, because the structure is treated as opaque even by the native code. All you really need is the pointer, passed back and forth; a perfect case for the first method I talked about above. So the declaration shown above is your winner.
The only battle now is obtaining a valid pointer to a libvlc instance that you can pass to the function whenever you call it. Chances are good that will come from a prior call to a function like libvlc_new, which is documented as creating and intializing a new libvlc instance. Its return value is exactly what you need here. So unless you've already created a libvlc instance (in which case, use that pointer), you will also need to call this function and store its result.
If the documentation is correct about the required values for the libvlc_new function's parameters, you can declare it very simply:
[DllImport("libvlc", EntryPoint = "libvlc_new", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewCore(int argc, IntPtr argv);
And call it thus:
IntPtr pLibVlc = NewCore(0, IntPtr.Zero);
// now pLibVlc should be non-zero
And of course, I know nothing about the VLC APIs, but my general knowledge of API design tells me that you will probably need to call the libvlc_release function with that same pointer to an instance once you're finished with it.
Try without the [MarshalAs(UnmanagedType.LPStr)], usually works for me.
I've recently moved a project I'm working on from .NET 3.5 to .NET 4. I'm using C#, Managed C++ and Unmanaged C++.
In one of my Managed C++ (interop) I'm having a static constructor:
public ref class StaticPool : public BaseStaticPools
{
public:
static StaticPool()
{
InitializePools();
}
static Poolable^ Dequeue()
{
return (Poolable^)Dequeue(Poolable::typeid);
}
private:
static void InitializePools()
{
BaseStaticPools::CreatePool(Poolable::typeid);
}
};
In .NET 3.5 once Dequeue() had been called for the first time it would trigger the static initialization, which runs the static constructor. Once I moved to .NET 4.0, the static constructor was never called.
I know there have been changes in static initializations in .NET 4.0, but according to all I read it should work fine.
In .NET, type initializers may only be called the first time a field is accessed. This is controlled by the [BeforeFieldInit] attribute.
I filed a bug report, which is only available to beta testers, despite being marked "Public".
Here's the explanation from Microsoft, which you may find helpful:
For C++, this is the intended behavior. We mark our classes with BeforeFieldInit, and so the initialization the CLR is performing is correct. We do not offer a way in C++/CLI to change this behavior. If you require the class constructor to run, you are able to call System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor explicitly.
Since we're invoking the standard here, the line from Partition I, 8.9.5 says this:
If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type.
That section actually goes into detail about how a language implementation can choose to prevent the behavior you're describing. C++/CLI chooses not to, rather they allow the programmer to do so if they wish.
Basically, since the code below has absolutely no static fields, the JIT is completely correct in simply not invoking static class constructors.
Jon Skeet wrote on this topic:
Type initialization changes in .NET 4.0
I'm trying to override the behavior of an external function in user32.dll because I don't want a certain window to show up.
What I'm trying to do is this:
[DllImport("user32.dll")]
public extern override IntPtr GetSystemMenu(IntPtr hMenu, bool bRevert)
{
return new IntPtr();
}
but this won't work because I get the following errors:
... no suitable method found to override
and
... cannot be extern and declare a body
Is there any way to simulate what I'm trying to do?
If the source code that calls GetSystemMenu is within your control then you can provide an alternative GetSystemMenu which delegates to the real one most of the time, but does something different for your special case.
If the source code that calls GetSystemMenu is outside your control then you will need to use hooks. In this situation you need to modify how user32.GetSystemMenu behaves which is entirely outside your codebase.
I think your problem stems from the fact that you're illegally adding an implementation to an external method declaration.
The C# specification (10.6.7 External methods) states that:
Because an external method declaration
provides no actual implementation, the
method-body of an external method
simply consists of a semicolon. An
external method may not be generic.
How do I declare in C# a C function that returns a pointer to a structure?
I believe following is one way to do that, followed by Marshal.PtrToStructure to get actual structure value.
// C-function
SimpleStruct * Function(void);
// C# import
[DllImport("MyDll.dll")]
public static extern IntPtr Function();
Am I correct about that?
Are there other ways to accomplish the same? (It would be OK to get struct back by value)
Since the function returns a pointer (hopefully not a locally allocated one?) your best bet is to manually marshal it (via Marshal.PtrToStructure).
If it were a parameter you could create a managed version of the structure using the PInvoke Interop Assistant then pass it via ref or out.
Caveat: this will only work if the pointer returned is to memory already managed by the CLR
I believe what you are looking for is
// C# import
[DllImport("MyDll.dll")]
[return : MarshalAs(UnmanagedType.LPStruct)]
public static extern StructureName Function();
[StructLayout(LayoutKind.Sequential)]
public class StructureName {}
This should eliminate the need for any manual Marshal.PtrToStructure calls. Depending on what your structure contains, you may need to tag some fields with MarshalAs attributes as appropriate. MSDN has a good example of this.
I am not an expert here at all, but I happened to be looking at a piece of code (that i don't understand completely mind you) that is doing this same thing.
Here is what they are doing
[DllImport("")]
private static extern short MethodName([In,Out] ref StructureName variable);
and then on the structure they have the following attribute
[StructLayout(LayoutKind.Sequential, Size = #)]
public struct StructureName {}
I think the part you are looking for is the [In,Out] part, and since it's being passed via ref, you should be getting the same data back.
marked as community wiki so people can fix this if wrong.