如何从C#调用c函数 [英] How do I call a c function from C#

查看:194
本文介绍了如何从C#调用c函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在C#中使用此C函数:

  typedef void(* WRITE_CALLBACK)(int hMountEnv,unsigned __int64 NumBytesWritten,
void * pContext);

我如何定义它,所以我可以调用它?



我需要做任何其他事情,使这项工作吗?

解决方案

查看 http://msdn.microsoft.com/en-us/library/ektebyzx(v = vs.80).aspx 如何元组函数指针。在页面底部有一个例子。



我会为你做C#,因为我不知道指针的方向,我将显示两者。有一些问题可能会涉及调用约定。 Marshal.GetDelegateForFunctionPointer Marshal.GetFunctionPointerForDelegate 假设函数指针将是StdCall,所以如果你没有访问非托管库,以确保函数指针是标准调用(我认为C默认为cdecl不幸的是),你必须创建一个非托管shim库来改变调用约定,除非有一些其他方式我不知道。



这将是我命名为UnmanagedLib.dll的C DLL的头。

  typedef void(__stdcall * WRITE_CALLBACK)(int hMountEnv,unsigned __int64 NumBytesWritten,void * pContext); 

externC{
__declspec(dllexport)WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void);
__declspec(dllexport)void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback);
}

这将是DLL的CPP文件。



#includeUnmanagedLib.h

void __stdcall SampleFunction(int hMountEnv,unsigned __int64 NumBytesWritten,void * pContext)
{
}

WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void)
{
return& SampleFunction;
}

void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback)
{
//样例调用
(* callback)(0,0,NULL)
}

最后,这是一个使用DLL的C#程序。 / p>

  class Program 
{
public delegate void WRITE_CALLBACK(int hMountEnv,ulong NumBytesWritten,IntPtr pContext);

[DllImport(UnmanagedLib.dll)]
public static extern IntPtr FunctionProducingFunctionPointer();

[DllImport(UnmanagedLib.dll)]
public static extern void FunctionConsumingFunctionPointer(IntPtr functionPointer);

public static void SampleFunction(int hMountEnv,ulong NumBytesWritten,IntPtr pContext)
{
}

static void Main(string [] args)
{
var functionDelegateToManagedSampleFunction = new WRITE_CALLBACK(SampleFunction);
var functionDelegateToUnmanagedSampleFunction = Marshal.GetDelegateForFunctionPointer(FunctionProducingFunctionPointer(),typeof(WRITE_CALLBACK));

//通过其指针调用非托管样本函数
functionDelegateToUnmanagedSampleFunction.DynamicInvoke(new object [] {0,0ul,null});

//将受管样本函数传递给非托管代码
FunctionConsumingFunctionPointer(Marshal.GetFunctionPointerForDelegate(functionDelegateToManagedSampleFunction));
}
}


I would like to use this C function in C#:

typedef void (*WRITE_CALLBACK)(int hMountEnv, unsigned __int64 NumBytesWritten, 
               void* pContext);

How would I go about defining it so I can call it?

Do I need to do anything else to make this work?

解决方案

Take a look at http://msdn.microsoft.com/en-us/library/ektebyzx(v=vs.80).aspx for how to marshal function pointers. There is an example on the bottom of that page.

I'll do the C# for you, and since I don't know which direction the pointer is going, I'll show both. There are some gotchas which could be problematic for you involving calling conventions. Marshal.GetDelegateForFunctionPointer and Marshal.GetFunctionPointerForDelegate assume the function pointer will be StdCall so if you don't have access to the unmanaged library to make sure the function pointer is standard call (I think C defaults to cdecl unfortunately), you'd have to create an unmanaged shim library to change the calling convention, unless there is some other way I don't know about.

This would be the header of a C DLL I named "UnmanagedLib.dll".

typedef void ( __stdcall *WRITE_CALLBACK)(int hMountEnv, unsigned __int64 NumBytesWritten, void* pContext);

extern "C" {
__declspec(dllexport) WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void);
__declspec(dllexport) void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback);
}

This would be the CPP file of the DLL.

#include "UnmanagedLib.h"

void __stdcall SampleFunction(int hMountEnv, unsigned __int64 NumBytesWritten, void* pContext)
{
}

WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void)
{
    return &SampleFunction;
}

void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback)
{
    // sample call
    (*callback)(0,0,NULL);
}

And lastly, this is a C# program to make use of the DLL.

class Program
{
    public delegate void WRITE_CALLBACK(int hMountEnv, ulong NumBytesWritten, IntPtr pContext);

    [DllImport("UnmanagedLib.dll")]
    public static extern IntPtr FunctionProducingFunctionPointer();

    [DllImport("UnmanagedLib.dll")]
    public static extern void FunctionConsumingFunctionPointer(IntPtr functionPointer);

    public static void SampleFunction(int hMountEnv, ulong NumBytesWritten, IntPtr pContext)
    {
    }

    static void Main(string[] args)
    {
        var functionDelegateToManagedSampleFunction = new WRITE_CALLBACK(SampleFunction);
        var functionDelegateToUnmanagedSampleFunction = Marshal.GetDelegateForFunctionPointer(FunctionProducingFunctionPointer(), typeof(WRITE_CALLBACK));

        // call the unmanaged sample function via its pointer
        functionDelegateToUnmanagedSampleFunction.DynamicInvoke(new object[] {0,0ul,null});

        // pass the managed sample function to the unmanaged code
        FunctionConsumingFunctionPointer(Marshal.GetFunctionPointerForDelegate(functionDelegateToManagedSampleFunction));
    }
}

这篇关于如何从C#调用c函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆