栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数据结构大作业-DBLP科学文献管理系统(四) Dll编写,C++与C#的数据交换

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构大作业-DBLP科学文献管理系统(四) Dll编写,C++与C#的数据交换

        终于讲完了后端代码,要涉及到前端的内容了。作为C++写的后台,而在Unity中是用C#中作为脚本语言。因此后台的代码想在前端进行调用,需要讲C++部分打包成Dll的动态链接库,约定好对应的格式,即可在C#中调用。

        首先需要了解C++/C#之前的主要区别,两种语言在语法上和关键字上很相似。这里体现的最主要的区别C#是托管堆代码,C++是非托管堆代码。在数据分配上C++每当用new等关键字申请空间时,编译器会在堆上为其分配内存,在使用完成后需要delete等回收空间,尤其注意在局部函数中申请的空间,一旦丢失了指向申请内存的指针,那么就会造成内存泄漏,即申请的内存空间和数据依然放在堆中,但是再也没办法使用和回收它(因为失去了地址去定位),当程序一直运行时,无效内存会越来越多,最终导致内存溢出崩溃(这就是我不怎么习惯用C++的一种原因,虽然现在已经有了auto_ptr等) 。

        而C#中的托管堆代码即将内存管理交给了OS和编译器,当一段内存没有被任何指针或变量引用后,就会由system.GC()自动回收 。基于这两种语言的特性,在C++中设计函数参数类型和数据交换时要考虑兼容性。

        这里列举一些常用的数据类型对应:

Windows Data Type

.NET Data Type

BOOL, BOOLEAN

Boolean or Int32

BSTR

String

BYTE

Byte

CHAR

Char

DOUBLE

Double

DWORD

Int32 or UInt32

FLOAT

Single

HANDLE (and all other handle types, such as HFONT and HMENU)

IntPtr, UintPtr or HandleRef

HRESULT

Int32 or UInt32

INT

Int32

LANGID

Int16 or UInt16

LCID

Int32 or UInt32

LONG

Int32

LPARAM

IntPtr, UintPtr or Object

LPCSTR

String

LPCTSTR

String

LPCWSTR

String

LPSTR

String or StringBuilder*

LPTSTR

String or StringBuilder

LPWSTR

String or StringBuilder

LPVOID

IntPtr, UintPtr or Object

LRESULT

IntPtr

SAFEARRAY

.NET array type

SHORT

Int16

TCHAR

Char

UCHAR

SByte

UINT

Int32 or UInt32

ULONG

Int32 or UInt32

VARIANT

Object

VARIANT_BOOL

Boolean

WCHAR

Char

WORD

Int16 or UInt16

WPARAM

IntPtr, UintPtr or Object

        这里只用了一些比较常用的。比如整数类型DWORd(C++)对应uint(C#),字符串传值时使用char*(C++)对应string/stringBuilder(C#)。

        其次是在C++中导出Dll,用vs可以很简单的创建一个C++Dll工程。

然后在.cpp文件写好函数,这里拿项目中需要得到一个string的哈希值做例子

DWORD Hash4(const string& tar) //计算哈希值函数
{
    DWORD64 ans = 0;
    for (int i = 0; i < tar.length(); i++) {
        ans = ((ans >> 8) & 0xf) ^ ((ans << 4) ^ tar[i]);
    }
    return ans & 0xfff;
}
DWORD GetHash(char* tar) 
{
    string temp = tar;
    return Hash4(temp);
}

在.h中补充函数原型,添加上extern "C" _declspec(dllimport)语句

#ifdef DL1_API
#else
#define DL1_API extern "C" _declspec(dllimport) //交给客户端使用时
#endif

DL1_API DWORD GetHash(char* tar);

         最后在C#中使用[DllImport]导入, static extern 并对上函数原型参数列表,中间的名称为打包出来的Dll文件名,注意如果是在unity中想使用dll,需要放在对应的assert/plugin文件夹中,即可加载dll数据库。只是普通的C#控制台程序和执行文件同目录即可

        注意制力用了char*与c#中的string交换,c++中的string不论是传出还是传入数据都是和C#对不上的,所以需要用到char*,中间还会涉及到一些编码问题。而c#中string和stringBuilder都可以在C++中被接受到。

[DllImport("Dll2")]
public static extern uint GetHash(string tar); //需要对应上参数类型和函数名

如果需要C#传入一个字符串,在C++中接收并进行修改,然后再由C#中得到结果,则需要用到stringBuilder,stringBuilder与string最大的不同在于stringBuilder可以预先分配空间,能够被多次的修改,并且不产生新的未使用对象(而string拷贝多了都是创建一个新的对象,非常耗时间)。在传值的时候建议使用stringBuilder,这里再拿程序中用到的搜索功能样例。

C++中函数原型:

void articleInfo(char* 文章名, char* 数据库地址, char* 结果);//输入文章名,返回文章的所有相关信息    

C#中:

using System.Text;
StringBuilder stringBuilder = new StringBuilder(50000);
[DllImport("Dll1")]
public static extern void articleInfo(String articleName, String saveUrl, StringBuilder pt);

至此,一个简单的Dll程序就这样设计完成,这里展示下程序中实际用到的所有接口。

    class DLL
    {
        public Thread thread;
        StringBuilder stringBuilder = new StringBuilder(50000);

        [DllImport("Dll1")]
        public static extern void articleInfo(String articleName, String saveUrl, StringBuilder pt);
        [DllImport("Dll1")]
        public static extern void main_Reader(String authorName, String saveUrl, StringBuilder pt);
        [DllImport("Dll1")]
        public static extern bool CheckFilePathCorrect_Compatible(string filePath, StringBuilder refS);
        [DllImport("Dll1")]
        public static extern bool CheckFilePathCorrect(string filePath);
        [DllImport("Dll1")]
        public static extern void CoAuthor(string search_name, string _saveUrl, StringBuilder pt);
        [DllImport("Dll1")]
        public static extern void initial_fuzzy(string filePath);
        [DllImport("Dll1")]
        public static extern int fuzzy_search(string filePath, uint threadNum, string content);
        [DllImport("Dll1")]
        public static extern void release_fuzzy_searcher();
        [DllImport("Dll1")]
        public static extern void Keyword_Sort(uint year, string filePath); //年份排序
        [DllImport("Dll2")]
        public static extern uint GetHash(string tar); //需要对应上参数类型和函数名
        [DllImport("Dll2")]
        public static extern bool ChechFilePathCorrect_dblp(string saveUrl);
        [DllImport("Dll1")]
        public static extern bool initial_readers(uint totalThread, uint maxThread, bool debugText, string saveUrl);//建库
        [DllImport("Dll1")]
        public static extern bool Author_Sort(string saveUrl); //作者排序
        [DllImport("Dll1")]
        public static extern int Full_word_match_fuzzy_search(string filePath, uint threadNum, string content);
        [DllImport("Dll1")]
        public static extern uint Format_Hash4(string tar); //哈希值
//C++中的原型

    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883674.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号