【问题标题】:C# function pointer?C#函数指针?
【发布时间】:2012-04-03 00:33:40
【问题描述】:

我在使用 C# 时遇到问题,我想在我的代码中获取方法的指针,但这似乎是不可能的。我需要该方法的指针,因为我想使用 WriteProcessMemory 不对其进行操作。我将如何获得指针?

示例代码

main()
{
    function1();
    function2();
}

function1()
{
    //get function2 pointer
    //use WPM to nop it (I know how, this is not the problem)
}
function2()
{
    Writeline("bla"); //this will never happen because I added a no-op.
}

【问题讨论】:

  • 这不是有效的 C# 代码。你想做什么?
  • 似乎与这个问题here 相似(非常)。它也可能对您有所帮助。
  • 您以(完全)错误的方式处理问题。为什么要不操作该方法?你可以这样做——但不同,取决于你的调用代码。
  • 由于 C# 是一种 JITted 语言,因此在您询问时,该函数的代码可能不存在。您的修补程序也可能会干扰 CLR,因为它还会玩有趣的游戏以进行 GC。使用调试 API 代替修补。
  • @RaymondChen:实际上您可以使用 Marshal.GetFunctionPointerForDelegate,(在 PInvoke 机制期间内部使用,因此您可以从非托管代码中获取到 C# 的回调) - 如果不是,这会强制方法的 JIT已经编译。但这不是重点。 user1276333 正在做的是一个坏主意 - JITted 代码是不可预测的,不应该被弄乱。

标签: c# pointers methods


【解决方案1】:

我知道这已经很老了,但是 C# 中的函数指针之类的例子是这样的:

class Temp 
{
   public void DoSomething() {}
   public void DoSomethingElse() {}
   public void DoSomethingWithAString(string myString) {}
   public bool GetANewCat(string name) { return true; }
}

...然后在你的主要或任何地方:

var temp = new Temp();
Action myPointer = null, myPointer2 = null;
myPointer = temp.DoSomething;
myPointer2 = temp.DoSomethingElse;

然后调用原函数,

myPointer();
myPointer2();

如果您的方法有参数,那么就像向您的操作添加通用参数一样简单:

Action<string> doItWithAString = null;
doItWithAString = temp.DoSomethingWithAString;

doItWithAString("help me");

或者如果你需要返回一个值:

Func<string, bool> getACat = null;
getACat = temp.GetANewCat;

var gotIt = getACat("help me");

【讨论】:

  • 哇,很好的答案。也许不是针对这个问题,但我学到了一些东西,它解决了我的问题。
  • +1 最佳答案!感谢您分享每个场景的示例(void -> void,args -> void,args -> return)
【解决方案2】:

编辑:我误读了你的问题,并没有看到关于想要 NOP 进行原始内存操作的声明。恐怕不建议这样做,因为正如 Raymond Chen 所说,GC 在内存中移动东西(因此在 C# 中使用了“pinned”关键字)。您可能可以通过反思来做到这一点,但您的问题表明您对 CLR 没有深入的了解。无论如何,回到我最初不相关的答案(我以为你只是想了解如何使用委托的信息):

C# 不是脚本语言 ;)

无论如何,C#(和 CLR)都有“函数指针”——除了它们被称为“委托”并且是强类型的,这意味着除了要调用的函数之外,您还需要定义函数的签名。

在你的情况下,你会有这样的事情:

public static void Main(String[] args) {

    Function1();

}

// This is the "type" of the function pointer, known as a "delegate" in .NET.
// An instance of this delegate can point to any function that has the same signature (in this case, any function/method that returns void and accepts a single String argument).
public delegate void FooBarDelegate(String x); 


public static void Function1() {

    // Create a delegate to Function2
    FooBarDelegate functionPointer = new FooBarDelegate( Function2 );

    // call it
    functionPointer("bla");
}

public static void Function2(String x) {

    Console.WriteLine(x);
}

【讨论】:

  • 可以 nop它(排序)。创建一个没有正文的 Function3 并将委托更改为 Function3 并让 Main 调用委托。
  • 委托不是函数指针。有一个函数指针,它被称为 IntPtr。检查:例如 Marshal.GetFunctionPointerForDelegate 方法。
  • @AdasLesniak 不正确,抱歉。 IntPtr 代表任何指针值,而不仅仅是函数指针 - 您也不能“调用”IntPtrGetFunctionPointerForDelegate 方法是让您将原始函数指针(由 IntPtr 表示)传递给其他本机代码。另请注意,您无法在 C# 中轻松操作 IntPtr 值。我的观点是语义委托一个(封装的)函数指针,但它比原始函数指针更好
【解决方案3】:
public string myFunction(string name)
{
    return "Hello " + name;
}

public string functionPointerExample(Func<string,string> myFunction)
{
    return myFunction("Theron");
}

Func functionName.. 使用它来传递方法。在这种情况下没有任何意义,但这基本上就是你将如何使用它

【讨论】:

    【解决方案4】:

    希望有用

    class Program
    {
    
        static void Main(string[] args)
        {
            TestPointer test = new TestPointer();
            test.function1();
        }
    }
    class TestPointer
    {
        private delegate void fPointer(); // point to every functions that it has void as return value and with no input parameter
        public void function1()
        {
            fPointer point = new fPointer(function2);
            point();
        }
        private void function2()
        {
            Console.WriteLine("Bla");
        }
    }
    

    【讨论】:

      【解决方案5】:

      无法直接从托管代码重写方法,但是可以使用非托管 .net 分析 API 来执行此操作。有关如何使用它的示例,请参阅thismsdn 文章。

      【讨论】:

        【解决方案6】:

        其实在 C# 9 中引入了真正的函数指针

        Official Documentation

        来自链接:

        您可以使用delegate* 语法定义函数指针。编译器将使用calli 指令调用函数,而不是实例化委托对象并调用Invoke

        【讨论】: