C#调用C动态链接库的实现

 更新时间:2024年01月21日 15:26:54   作者:zhuliang27  
动态链接库是不能直接执行的,也不能接收消息,它只是一个独立的文件,本文主要介绍了C#调用C动态链接库的实现,具有一定的参考价值,感兴趣的可以了解一下

前言

已经没写过博客好久了,上一篇还是1年半前写的LTE Gold序列学习笔记,因为工作是做通信协议的,然后因为大学时没好好学习专业课,现在理论还不扎实,不敢瞎写;

因为工作原因,经常需要分析一些字节流数据,所以基本都是用C写的,结果输出在命令行,或者txt/csv文件;但个人还是喜欢输出到GUI界面,可选的手段就MFC、WinForm、PyQt:

MFC的话感觉多少有点过时了,所以用WinForm,PyQt的多点,尤其是WinForm很方便;前段时间用WinForm写了个日志分析工具,因为本人是业余的C#使用者,所以写的很痛苦,至于数据处理的核心思想就CSDN上的结构体字节流的相互处理,数据处理部分大概1000来行;但工作中用的结构体通常很大,涉及大小端转换,同时还有位域,处理起来很麻烦,用C的话就很方便,所以用C处理数据用WinForm、PyQt显示的方法比较方便;所以就想着用C处理玩数据保存到txt/csv文件,然后用C#/Python去调用C应用并读取文件,但感觉有点low;所以就打算把C部分的处理输出成dll文件,然后用C#/Python去调用DLL;当然对我的需求来说,把所有数据封装到1个结构体里面,每个结构体字段是Uint或者Uint数组即可;以下部分实现就仅仅是能用即可,没具体设置;

C语言部分-编译生成动态链接库

我办公电脑上是VS2015,自己电脑是VS2017,创建工程有点差异;

VS2015工程设置使用CSDN上面的截图,注意源文件后缀用默认的cpp,不要用c,我还没去学习这块的细节,反正能用就行

e3f1ed83fb834fde8ee35059faf95a7e.png

VS2017生成控制台应用程序后,需要将如下红框中的配置类型修改为动态库;

e9e57bfe1ad04f1393eac89c494253f0.png

然后代码和C应用程序的差异的话就在函数声明或定义前加上

extern "C" _declspec(dllexport) int add_test(int x, int y);

不设置配置和平台的话,默认输出就在Debug路径下生成和项目名一样的DLL文件,如下图:

969a592af5c049aabc4abafe8e198d45.png

C#部分-使用动态链接库

把编译生成的DLL文件放到C#编译输出的路径下,不配置的话就在如下路径:

ea1bae29460546589e5df985681b9f3e.png

在C#中调用C的话,核心代码就如下2行,

[DllImport("DLLTEST.dll",CallingConvention=CallingConvention.Cdecl)]
extern static int add_test(int x, int y);

还有需要注意的点,需要包含如下引用,当然写了如上第一行就会提示让包含了:

using System.Runtime.InteropServices;

感觉像是函数外部声明,能用就行,暂时没有去深究原理啥的,输出如下:

0e51a0b0e0bd4f75af5d6b424f0c7bf7.png

因为需要处理的数据通常比较多,所以就定义一个结构体,把需要传输的数据全放里面,然后用1个接口就读过去了;

简单做个测试

  • C程序定义一个结构体,结构体里面仅包含一个字段,字段是一个Uint类型的数组:
typedef struct
{
	unsigned int data[32];
}RetData;
  • C程序输出结构体数据测试:
void get_array(RetData* ret)
{
	for (int idx = 0; idx < 32; idx++)
	{
		ret->data[idx] = idx * 10;
	}
}
  • C#程序也定义一个结构体,结构体包含一个字段,字段是Uint32类型的数组:
    struct GetData
    {
        [MarshalAs(UnmanagedType.ByValArray,SizeConst =32)]
        public UInt32[] data;
    }
  • C#程序读入结构体数据测试,可能用法很不专业,能读出来就行

/* 函数外部声明 */
[DllImport("DLLTEST.dll", CallingConvention = CallingConvention.Cdecl)]
extern static void get_array(ref GetData ret);

/* 在Main函数中调用 */
GetData getData = new GetData();
get_array(ref getData);
  • 输出

f9732d18d81f40b8a7af00e1fa44496d.png

今天下午在公司写了个维测工具,整个流程和上面测试步骤一致,能正常使用

Python部分-使用动态链接库

把编译生成的DLL文件放到Python文件同级路径下,这样在Python代码中就直接使用DLL文件名即可,Python测试代码如下,调用数组那块先前在公司测试正常能用来自,忘了,懒得写了

import ctypes
dll = ctypes.windll.LoadLibrary('DLLTEST.dll')
print(dll.add_test(4, 5))

输出5:如下图:

0b803cd97e2a4c9ea73a8bd59f0e85b6.png

本来打算把整个工程打包放到CSDN来着,但免费的话审核不通过,所以就把C/C#部分代码都贴下面了:

C程序头文件

#pragma once
#ifndef DLL_TEST_H
#define DLL_TEST_H

typedef struct
{
	unsigned int data[32];
}RetData;

extern "C" _declspec(dllexport) int add_test(int x, int y);
extern "C" _declspec(dllexport) void get_array(RetData* ret);

#endif // !DLL_TEST_H

C程序源文件

#include <stdio.h>
#include <stdlib.h>
#include "dll_test.h"

int add_test(int x, int y)
{
	return x + y;
}

void get_array(RetData* ret)
{
	for (int idx = 0; idx < 32; idx++)
	{
		ret->data[idx] = idx * 10;
	}
}

C#程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{

    struct GetData
    {
        [MarshalAs(UnmanagedType.ByValArray,SizeConst =32)]
        public UInt32[] data;
    }

    class Program
    {
        [DllImport("DLLTEST.dll",CallingConvention=CallingConvention.Cdecl)]
        extern static int add_test(int x, int y);

        [DllImport("DLLTEST.dll", CallingConvention = CallingConvention.Cdecl)]
        extern static void get_array(ref GetData ret);

        static void Main(string[] args)
        {
            Console.WriteLine("{0} + {1} = {2}", 4, 5, add_test(4, 5));
            GetData getData = new GetData();
            get_array(ref getData);
            Console.ReadLine();
        }
    }
}

到此这篇关于C#调用C动态链接库的实现的文章就介绍到这了,更多相关C#调用C动态链接库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • C#实现将HTML转换成纯文本的方法

    C#实现将HTML转换成纯文本的方法

    这篇文章主要介绍了C#实现将HTML转换成纯文本的方法,基于自定义类实现文本转换功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • 基于C#实现Windows服务的方法详解

    基于C#实现Windows服务的方法详解

    在实际应用过程中,有时候我们希望开发的程序,不需要界面,直接开机就可以长时间运行,这时候,我们可以考虑做成一个Windows服务。这篇文章跟大家介绍一下,如何基于C#实现Windows服务的创建、安装、启动、停止和卸载,需要的可以参考一下
    2022-09-09
  • C#通过System.CommandLine快速生成支持命令行的应用程序

    C#通过System.CommandLine快速生成支持命令行的应用程序

    这篇文章介绍了C#通过System.CommandLine快速生成支持命令行应用程序的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • C# Newtonsoft.Json用法详解

    C# Newtonsoft.Json用法详解

    本文主要介绍了C# Newtonsoft.Json用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Entity Framework配置关系

    Entity Framework配置关系

    这篇文章介绍了Entity Framework配置关系的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • c# 判断指定文件是否存在的简单实现

    c# 判断指定文件是否存在的简单实现

    这篇文章主要介绍了c# 判断指定文件是否存在的简单实现,需要的朋友可以参考下
    2014-02-02
  • WPF调用WindowsAPI实现屏幕录制

    WPF调用WindowsAPI实现屏幕录制

    这篇文章主要为大家详细介绍了WPF如何调用WindowsAPI实现屏幕录制,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
    2023-05-05
  • HTML文本框的值改变后触发后台代码的方法

    HTML文本框的值改变后触发后台代码的方法

    asp.net用日期插件,当选中一个日期时触发一个事件,以查询当前日期的数据。这是要跟数据库交互的。先贴出控件代码:
    2013-04-04
  • WPF+ASP.NET SignalR实现后台通知功能的示例代码

    WPF+ASP.NET SignalR实现后台通知功能的示例代码

    本文以一个简单示例,简述如何通过WPF+ASP.NET SignalR实现消息后台通知以及数据的实时刷新,仅供学习分享使用,如有不足之处,还请指正
    2022-09-09
  • C# WPF如何反射加载Geometry几何图形数据图标

    C# WPF如何反射加载Geometry几何图形数据图标

    这篇文章主要介绍了C# WPF如何反射加载Geometry几何图形数据图标,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03

最新评论