C#如何调用C写的Win32 DLL

本文介绍如何在Visual Studio中创建一个C++ DLL项目,并通过C#控制台项目调用其中的方法。首先,使用Visual C++创建DLL类型项目,定义并实现一个C方法HelloWorld()。然后,在C#项目中,使用DllImport属性调用DLL中的方法,成功展示跨语言调用。

1. 首先,在Visual Studio中,我们建立一个Visual C++的项目

    类型选择Win32 Project,继续选择Dll类型

    该项目取名叫做myDll

    1) 添加myDll.h头文件,代码如下:

#ifdef A_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

extern "C" DLL_API void HelloWorld();

    这里HelloWorld()就是等下我们要暴露给C#调用的C方法。

    注意:必须给函数增加extern "C"关键字,否则等下将无法找到该

             函数的入口点。

  

    2)添加myDll.cpp文件,代码如下:

#include "stdafx.h"
#include 
"myDll.h"

#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    
switch (ul_reason_for_call)
    {
        
case DLL_PROCESS_ATTACH:
        
case DLL_THREAD_ATTACH:
        
case DLL_THREAD_DETACH:
        
case DLL_PROCESS_DETACH:
        
break;
    }

    
return TRUE;
}

void HelloWorld()
{
    MessageBox(NULL, TEXT(
"Hello World"), TEXT("In a DLL"), MB_OK);
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

 

 

 2. 编译成功!接下来我们便可以添加一个C#控制台项目了

     C#测试代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TestDll
{
    
class Program
    {
        [DllImport(
"myDll.dll")]
        
public extern static void HelloWorld();

        
static void Main(string[] args)
        {
            HelloWorld();
        }
    }
}

 

  在这里我要特别指出的是两点:

1) 必须使用如下命名空间

using System.Runtime.InteropServices

 

2) 对于原Dll文件中C方法的wrapper

        [DllImport("myDll.dll")]
        
public extern static void HelloWorld();

 

运行程序,会看到弹出Hello World对话框!

 

转载于:https://www.cnblogs.com/davidgu/archive/2011/06/21/2086024.html

### C# 调用 Win32 C++ DLL 的方法与示例 在 C#调用 Win32C++ DLL 文件,通常需要通过 P/Invoke(平台调用)机制实现。P/Invoke 是一种允许托管代码(如 C#调用非托管代码(如 C++DLL)的技术。以下是详细说明和示例代码。 #### 1. 使用 `DllImport` 属性声明外部函数 在 C# 中,可以使用 `[DllImport]` 属性声明要调用C++ DLL 函数。需要注意的是,C++ 函数必须以 `extern "C"` 声明,并使用 `__declspec(dllexport)` 导出[^1]。 以下是一个简单的 C++ DLL 示例: ```cpp // C++ DLL (MyDll.cpp) #define MYDLL_API __declspec(dllexport) extern "C" { MYDLL_API int Add(int a, int b); } int Add(int a, int b) { return a + b; } ``` 编译生成 DLL 后,在 C# 中可以通过以下方式调用: ```csharp using System; using System.Runtime.InteropServices; class Program { // 使用 DllImport 声明外部函数 [DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall)] public static extern int Add(int a, int b); static void Main(string[] args) { int result = Add(5, 3); // 调用 DLL 中的 Add 函数 Console.WriteLine($"Result: {result}"); } } ``` #### 2. 数据类型的映射 C++C# 的数据类型并不完全一致,因此在调用时需要进行适当的映射。例如,C++ 中的指针类型可以通过 `ref` 或 `out` 关键字在 C# 中表示[^4]。 以下是一个传递指针的示例: ```cpp // C++ DLL (MyDll.cpp) #define MYDLL_API __declspec(dllexport) extern "C" { MYDLL_API void MultiplyByTwo(int* value); } void MultiplyByTwo(int* value) { *value *= 2; } ``` 对应的 C# 调用代码如下: ```csharp using System; using System.Runtime.InteropServices; class Program { [DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall)] public static extern void MultiplyByTwo(ref int value); static void Main(string[] args) { int number = 5; MultiplyByTwo(ref number); // 调用 DLL 中的 MultiplyByTwo 函数 Console.WriteLine($"Result: {number}"); } } ``` #### 3. 调用带有字符串参数的函数 如果 C++ DLL 中的函数涉及字符串参数,则需要特别注意字符串编码问题。通常情况下,C++ 中的字符串为 ANSI 或 UTF-8 编码,而 C# 默认使用 Unicode 编码。可以通过设置 `DllImport` 属性的 `CharSet` 参数来解决编码问题[^1]。 以下是一个示例: ```cpp // C++ DLL (MyDll.cpp) #define MYDLL_API __declspec(dllexport) extern "C" { MYDLL_API void PrintString(const char* str); } void PrintString(const char* str) { printf("%s\n", str); } ``` 对应的 C# 调用代码如下: ```csharp using System; using System.Runtime.InteropServices; class Program { [DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] public static extern void PrintString(string str); static void Main(string[] args) { PrintString("Hello from C#"); // 调用 DLL 中的 PrintString 函数 } } ``` #### 4. 注意事项 - **调用约定**:确保 C++ 函数和 C# 方法的调用约定一致。常见的调用约定包括 `stdcall` 和 `cdecl`,默认情况下,Win32 API 使用 `stdcall`。 - **DLL 文件路径**:确保运行时能够找到 DLL 文件。可以将 DLL 放置在可执行文件的同一目录下,或者添加到系统的 PATH 环境变量中。 - **位数匹配**:如果目标平台为 64 位系统,则需要生成 64 位版本的 DLL;如果为 32 位系统,则需要生成 32 位版本的 DLL[^3]。 #### 5. 扩展功能 如果需要更复杂的交互,可以考虑使用 C++/CLI(托管 C++)作为桥梁,将非托管的 C++ 代码封装为托管类库,从而简化调用过程[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值