VS创建C++动态库和C#访问过程

以C++ 14版本和net 8.0为例,使用vs2022工具

1 新建项目

2 添加类文件

3 项目文件列表如下

4 写头文件

cpp 复制代码
#pragma once

#ifdef TIMECONVERTER_EXPORTS
#define TIMECONVERTER_API __declspec(dllexport)
#else
#define TIMECONVERTER_API __declspec(dllimport)
#endif

extern "C" 
{

    // 将时间转换为字符串
    TIMECONVERTER_API const char* ConvertTimeToString(int year, int month, int day,
        int hour, int minute, int second);

    TIMECONVERTER_API const char* GetCurrentTimeString();
    // 释放字符串内存
    TIMECONVERTER_API void FreeString(char* str);
}

5 写cpp文件

cpp 复制代码
#include "pch.h"

#include "TimeConverter.h"
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>

using namespace std;

// 导出的函数:将时间转换为字符串
extern "C" TIMECONVERTER_API const char* ConvertTimeToString(int year, int month, int day,
    int hour, int minute, int second)
{
    try {
        // 验证输入参数
        if (year < 1900 || year > 2100) return nullptr;
        if (month < 1 || month > 12) return nullptr;
        if (day < 1 || day > 31) return nullptr;
        if (hour < 0 || hour > 23) return nullptr;
        if (minute < 0 || minute > 59) return nullptr;
        if (second < 0 || second > 59) return nullptr;

        // 格式化时间字符串
        stringstream ss;
        ss << setw(4) << setfill('0') << year << "-"
            << setw(2) << setfill('0') << month << "-"
            << setw(2) << setfill('0') << day << " "
            << setw(2) << setfill('0') << hour << ":"
            << setw(2) << setfill('0') << minute << ":"
            << setw(2) << setfill('0') << second;

        string result = ss.str();

        // 分配内存并返回字符串
        char* output = new char[result.length() + 1];
        strcpy_s(output, result.length() + 1, result.c_str());

        return output;
    }
    catch (...) {
        return nullptr;
    }
}

// 导出的函数:释放字符串内存
extern "C" TIMECONVERTER_API void FreeString(char* str)
{
    if (str != nullptr)
    {
        delete[] str;
    }
}


extern "C" TIMECONVERTER_API const char* GetCurrentTimeString()
{
    try {
        time_t now = time(nullptr);
        tm timeInfo;
        localtime_s(&timeInfo, &now);

        return ConvertTimeToString(
            timeInfo.tm_year + 1900,
            timeInfo.tm_mon + 1,
            timeInfo.tm_mday,
            timeInfo.tm_hour,
            timeInfo.tm_min,
            timeInfo.tm_sec
        );
    }
    catch (...)
    {
        return nullptr;
    }
}

6 注意配置信息

配置属性 → C/C++ → 预处理器 → 预处理器定义:添加 TIMECONVERTER_EXPORTS

配置属性 → 常规 → 配置类型:动态库(.dll)


7 新建C#项目拷贝dll文件

拷贝C++的dll文件到C#项目生成文件目录下

8 引用dll测试

csharp 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace StringTimeTest
{
    public partial class UserControl1: UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Console.WriteLine("C++ 时间转换器测试");
            Console.WriteLine("==================");
            TestTimeConversion("当前时间");
            // 测试用例1:当前时间
            TestTimeConversion(2024, 1, 15, 14, 30, 45, "测试用例1 - 当前时间");

            // 测试用例2:午夜时间
            TestTimeConversion(2024, 12, 31, 0, 0, 0, "测试用例2 - 午夜时间");

            // 测试用例3:边界值测试
            TestTimeConversion(2024, 1, 1, 23, 59, 59, "测试用例3 - 边界值");

            // 测试用例4:无效时间(应该返回空)
            TestTimeConversion(2024, 13, 32, 25, 61, 61, "测试用例4 - 无效时间");

            // 测试用例5:使用DateTime.Now
            DateTime now = DateTime.Now;
            TestTimeConversion(now.Year, now.Month, now.Day,
                             now.Hour, now.Minute, now.Second,
                             "测试用例5 - 实时时间");

            Console.WriteLine("\n按任意键退出...");
         
        }

        // 导入C++ DLL函数
        [DllImport("TimeConverter.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr ConvertTimeToString(int year, int month, int day,
                                                       int hour, int minute, int second);

        [DllImport("TimeConverter.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void FreeString(IntPtr str);

        [DllImport("TimeConverter.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr GetCurrentTimeString();



        static void TestTimeConversion(int year, int month, int day,
                                     int hour, int minute, int second, string testName)
        {
            Console.WriteLine($"\n{testName}:");
            Console.WriteLine($"输入: {year}-{month:D2}-{day:D2} {hour:D2}:{minute:D2}:{second:D2}");

            IntPtr resultPtr = ConvertTimeToString(year, month, day, hour, minute, second);

            if (resultPtr != IntPtr.Zero)
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                Console.WriteLine($"输出: {result}");

                // 释放C++分配的内存
                FreeString(resultPtr);
            }
            else
            {
                Console.WriteLine("输出: 无效的时间参数!");
            }
        }
        static void TestTimeConversion( string testName)
        {
            Console.WriteLine($"\n{testName}:");
      

            IntPtr resultPtr = GetCurrentTimeString();

            if (resultPtr != IntPtr.Zero)
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                Console.WriteLine($"输出: {result}");

                // 释放C++分配的内存
                FreeString(resultPtr);
            }
            else
            {
                Console.WriteLine("输出: 无效的时间参数!");
            }
        }
    }
}
相关推荐
RemainderTime17 小时前
从零搭建Spring Boot3.x生产级单体脚手架项目(JDK17 + Nacos + JWT + Docker)
java·spring boot·架构
黯叶17 小时前
基于 Docker+Docker-Compose 的 SpringBoot 项目标准化部署(外置 application-prod.yml 配置方案)
java·spring boot·redis·docker
say_fall17 小时前
泛型编程基石:C++ 模板从入门到熟练
java·开发语言·c++·编辑器·visual studio
代码笔耕17 小时前
写了几年 Java,我发现很多人其实一直在用“高级 C 语言”写代码
java·后端·架构
txinyu的博客18 小时前
结合游戏场景解析UDP可靠性问题
java·开发语言·c++·网络协议·游戏·udp
de之梦-御风18 小时前
【Winform】实现“下拉自动补全”通常指的是 ComboBox / TextBox 在输入时自动提示或补全匹配项
c#
一路向北North18 小时前
springboot基础(85): validator验证器
java·spring boot·后端
郝学胜-神的一滴18 小时前
深入解析Mipmap层级判定原理:从理论到实践
c++·unity·godot·游戏程序·图形渲染·unreal engine
雾岛听蓝18 小时前
探索C++继承机制
开发语言·c++
1.14(java)18 小时前
掌握数据库约束:确保数据精准可靠
java·数据库·mysql·数据库约束