How to implement C++ style function pointers in C#?, Without using delegates
Asked Answered
M

6

7

I am learning pointers in C# and was curious if one can use C++ style function pointers in C#. Yes, I know C# has its own equivalent concept for Function Pointers(called as delegates). But I just want to know if the same can be achieved using pointers in C#, without using delegates.

If using pointers is completely legal in C#(using unsafe option) and pointer semantics is almost similar to C/C++ then in my opinion one should also be able to use C/C++ style function pointers as well. Please guide me on this. Is it possible? If yes how?, If not then why?

Please notice the similarity of pointer usage in C# and C/C++ as depicted in below example

/* Using pointers in C# (Very similar to C/C++) */
using System;

namespace UnsafeCodeApplication
{
   class TestPointer
   {
      public unsafe static void Main()
      {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)

         /* let us have array address in pointer */
         for ( int i = 0; i < 3; i++)
         {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }

         Console.ReadKey();
      }
   }
}
Matthus answered 11/4, 2016 at 20:51 Comment(6)
quick note: C# does not have functions, but google for UnmanagedFunctionPointerEasing
but there is similar thing in C# called methods. And BTW Both are same, there is no difference its just a different term for the same thing in C#. In object-oriented programming, a method is a subroutine (or procedure or function) associated with a class. With respect to Object Oriented programming the term "Method" is used, not functions. Refer this : #12259464Matthus
and pointer to method in C# is called... delegateEasing
I prefer to refer this: #156109Easing
What are you trying to achieve by function pointers ? I guess you can use C++/CLI and do whatever you want. Store pointer to anything using IntPtr, if you want to call C# function, pin it from C++ side, and also call however you want. You could even generate ILCode and mess around with assembly, but how deep you really want to go ?Kasiekask
@Lashane: A delegate is an object that is an abstraction around a function pointer (and its receiver). The question is whether C# also supports manipulating function pointers directly. The CLR permits this, so it is reasonable to suppose that C# provides some syntax for doing so. However, it does not.Derinna
D
15

The other answers which note that C# has no built-in support whatsoever for function pointers, even in unsafe mode, are correct.

It is interesting to consider what it would take to implement this feature. As it happens, I have implemented this feature in an unreleased prototype version of C# back in... 2010? Around then. Maybe 2011.

We decided upon review of the prototype that the syntax was insufficiently pleasant and the usage cases were insufficiently compelling to justify going forward with the feature.

First off, what is the compelling benefit of the feature over delegates? Delegates are typesafe and nicely capture the semantics of a reference to a function bound to its receiver. However, in some "systems" scenarios -- the same scenarios in which you would be using raw pointers to memory in the first place -- delegates are simply too heavyweight. They are garbage collected, they increase collection pressure, they're a large object compared to the size of a pointer, they have costs on every invocation, and so on. Or, you might be constructing your own custom layout vtables to interoperate with some particularly nasty bit of unmanaged code, and you wish to invoke a function pointer that you've just put down in your vtable. And so on.

The CLR has the necessary instruction:calli, a pointer-indirected call. But there is no syntactic construct in C# whatsoever that will cause the C# compiler to emit this instruction.

So what's the problem? Just add some syntax that causes this to be emitted, right?

The problem is: what syntax? In order to ensure that the CLR's physical stack remains aligned correctly, the compiler must know the signature of the method being invoked via the pointer. Of course we already have a mechanism for saying what the signature of a method is: that's called a delegate, and we've already rejected the use of such a thing. Moreover, remember, we are talking here about the physical stack that is actually going to be manipulated, not the CLR's abstract evaluation stack. The signature of the function invoked must include things like whether the function pointer is cdecl or syscall, for instance.

We struggled for some time to come up with something that did not look hideous, and whichever way we tried, it looked more hideous. I actually do not recall what notation we ended up implementing for the prototype; I think I may have blocked it out. I might have it in my notes somewhere, but unfortunately I do not have time to look right now.

The feature is still brought up every now and again. The current management of the C# team has a history with using managed languages in low-level applications, so now might be a good time to pitch it again if you have a strong use case.

Derinna answered 11/4, 2016 at 22:9 Comment(0)
G
5

While supported by the CLR, the C# language limits you to safe unsafe code. Function pointers fall in the unsafe unsafe category, they can very easily imbalance the stack. A nasty mishap that has long-term consequences, making code misbehave long after the mishap occurred. This site got its name for a good reason, this kind of bug is SOE factorial. Even the C++ compiler adds a runtime check to verify that no stack imbalance occurred.

You still have options. You can use raw function pointers by using Reflection.Emit or C++/CLI. Or achieve the moral equivalent by using Delegate.DynamicInvoke(). The latter is always safe, the CLR performs a runtime check to verify that enough arguments are passed.

Which is the surely the solution you should consider pursuing, albeit that it is not clear why you ask. Delegates are extraordinarily micro-optimized with massive amounts of code in the CLR to make them fast. That code does the equivalent of Reflection.Emit but in machine code. You can't beat it.

Geopolitics answered 11/4, 2016 at 22:19 Comment(0)
P
2

No, there is nothing in C# closer to function pointers from C++ than delegates. C# Pointers may operate on following types:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
  • Any enum type.
  • Any pointer type.
  • Any user-defined struct type that contains fields of unmanaged types only.

Source: https://msdn.microsoft.com/en-us/library/y31yhkeb.aspx

It is not always possible to give the pointer to function to the user as it is done in native code. C# code is compiled to CLR and not to native code.

In .NET 1.1 there was Econo-JIT mode, in which native code for functions could be deleted after function was invoked. Function could have different address everytime it was invoked.

Posterity answered 11/4, 2016 at 21:4 Comment(5)
By this phrase : Pointers may operate on following types , did you mean pointers in C#?Matthus
Could you please read the answer more carefully? Thanks for your comment. :)Theresatherese
@ShashikantMitkari Yes, exactly.Pasteur
What does the JIT have to do with the question?Tolerant
@Theodoros Chatzigiannakis I updated my answer. It appears that JIT was relevant in old versions of .NET, but it is no longer the case. Thank you for asking.Pasteur
C
2

C# 9 allows Function Pointers: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/function-pointers

The language will allow for the declaration of function pointers using the delegate* syntax. The full syntax is described in detail in the next section but it is meant to resemble the syntax used by Func and Action type declarations. These types are represented using the function pointer type as outlined in ECMA-335. This means invocation of a delegate* will use calli where invocation of a delegate will use callvirt on the Invoke method. Syntactically though invocation is identical for both constructs.

Method groups will now be allowed as arguments to an address-of expression. The type of such an expression will be a delegate* which has the equivalent signature of the target method and a managed calling convention.

Take a look below at my simple example of how to use this feature. In the properties of the project select the "Build" tab and check "Allow unsafe code".

    using System;

    namespace ConsoleApp4
    {
        class Program
        {
            public static void LogMyMethodCall() => Console.WriteLine("MyMethod has been called");
            public unsafe class Example
            {
                public void MyMethod(Action<int> a, delegate*<void> f)
                {
                    a(1);
                    f();
                }
            }

            public unsafe static void Main(string[] args)
            {
                var e = new Example();
                e.MyMethod(x => Console.WriteLine($"{x} has been passed to MyMethod"), &LogMyMethodCall);
                Console.ReadLine();
            }
        }
    }    

   
Chairborne answered 13/10, 2020 at 15:22 Comment(1)
this should be the answer to this question.Embank
C
1

C# has no pointers to functions, and as matter of fact the only reason C# has pointers to value types is for interop with C/C++ and Win API. Delegates have you covered.

C# is very different coding paradigm from C++. Do not let semantics similarities confuse you. Two VERY different languages that require VERY different mindset.

Cerallua answered 11/4, 2016 at 21:33 Comment(0)
J
0

Have a look at this , void *p is your pointer to function(Hex Value,Ram Address)

class Program
{

    static void Main(string[] args)
    {
        //
        OurCallback();

    }
    public static IntPtr GetFunctionPointer()
    {
        A obj1 = new A();
        RuntimeMethodHandle method = ((Action)obj1.Method1).Method.MethodHandle;
        IntPtr p = method.GetFunctionPointer();
        return p;
    }
    public unsafe static void OurCallback()
    {
      var k =  GetFunctionPointer();
      void* p = k.ToPointer();

    }
    struct A
    {
        public void Method1()
        {
            Console.WriteLine("\nTest!");
        }
    }
}

More Version If your External Library Use CallBacks this version is more Good

   [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public unsafe delegate void CallbackFunc(void* hPreviewCallback, void* 
    pParam);

    private unsafe static void HandleDecData(void* hPreviewCallback, void* 
    pParam)
    {

        // Here you can handle callback

    }
Jillian answered 20/2, 2019 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.