Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement my own type of extern?

In our product, we have things called "services" which are the basic means of communication between different parts of the product (and especially between languages—an in-house language, C, Python and .NET).

At present, code is like this (Services.Execute utilising params object[] args):

myString = (string)Services.Execute("service_name", arg1, arg2, ...);

I'd rather like to be able to write code like this and get the benefits of type checking and less verbose code:

myString = ServiceName(arg1, arg2, ...);

This can be achieved with a simple function,

public static string ServiceName(int arg1, Entity arg2, ...)
{
    return (string)Services.Execute("service_name", arg1, arg2, ...);
}

But this is rather verbose, and not quite so easy to manage when doing it for scores of services, as I intend to be doing.

Seeing how extern and the DllImportAttribute work, I hope it should be possible to hook this up by some means like this:

[ServiceImport("service_name")]
public static extern string ServiceName(int arg1, Entity arg2, ...);

But I don't know how to achieve this at all and can't seem to find any documentation for it (extern seems to be a fairly vaguely defined matter). The closest I've found is a somewhat related question, How to provide custom implementation for extern methods in .NET? which didn't really answer my question and is somewhat different, anyway. The C# Language Specification (especially, in version 4.0, section 10.6.7, External methods) doesn't help.

So, I want to provide a custom implementation of external methods; can this be achieved? And if so, how?

like image 426
Chris Morgan Avatar asked Dec 06 '12 02:12

Chris Morgan


People also ask

Can we initialize extern variable in C?

You can initialize any object with the extern storage class specifier at global scope in C or at namespace scope in C++. The initializer for an extern object must either: Appear as part of the definition and the initial value must be described by a constant expression; or.

How do you declare an extern function?

You can declare the function as extern int sum(int a, int b) instead but this will only cause redundancy.

How do you use an extern variable in multiple files?

Best way to declare and define global variables The clean, reliable way to declare and define global variables is to use a header file to contain an extern declaration of the variable. The header is included by the one source file that defines the variable and by all the source files that reference the variable.

What is extern type in C++?

The extern keyword may be applied to a global variable, function, or template declaration. It specifies that the symbol has external linkage. For background information on linkage and why the use of global variables is discouraged, see Translation units and linkage.


1 Answers

The C# extern keyword does very little, it just tells the compiler that the method declaration won't have a body. The compiler does a minimum check, it insists that you provide an attribute as well, anything goes. So this sample code will compile just fine:

   class Program {
        static void Main(string[] args) {
            foo();
        }

        class FooBar : Attribute { }

        [FooBar]
        static extern void foo();
    }

But of course it will not run, the jitter throws its hands up at the declaration. Which is what is required to actually run this code, it is the jitter's job to generate proper executable code for this. What is required is that the jitter recognizes the attribute.

You can see this done in the source code for the jitter in the SSCLI20 distribution, clr/src/md/compiler/custattr.cpp source code file, RegMeta::_HandleKnownCustomAttribute() function. That's code that's accurate for .NET 2.0, I'm not aware of additions to it that affect method calling. You'll see it handling the following attributes that relate to code generation for method calls, the kind that will use the extern keyword:

  • [DllImport], you no doubt know it

  • [MethodImpl(MethodImplOptions.InternalCall)], an attribute that's used on methods that are implemented in the CLR instead of the framework. They are written in C++, the CLR has an internal table that links to the C++ function. A canonical example is the Math.Pow() method, I described the implementation details in this answer. The table is not otherwise extensible, it is hard-baked in the CLR source code

  • [ComImport], an attribute that marks an interface as implemented elsewhere, invariably in a COM server. You rarely program this attribute directly, you'd use the interop library that's generated by Tlbimp.exe instead. This attribute also requires the [Guid] attribute to give the required guid of the interface. This is otherwise similar to the [DllImport] attribute, it generates a pinvoke kind of call to unmanaged code but using COM calling conventions. This can of course only work properly if you actually have the required COM server on your machine, it is otherwise infinitely extensible.

A bunch more attributes are recognized in this function but they don't otherwise relate to calling code that's defined elsewhere.

So unless you write your own jitter, using extern isn't a viable way to get what you want. You could consider the Mono project if you want to pursue this anyway.

Common extensibility solutions that are pure managed are the largely forgotten System.AddIn namespace, the very popular MEF framework and AOP solutions like Postsharp.

like image 164
Hans Passant Avatar answered Sep 18 '22 18:09

Hans Passant