惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
V
V2EX
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Hugging Face - Blog
Hugging Face - Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
Recent Announcements
Recent Announcements
Vercel News
Vercel News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
美团技术团队
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
J
Java Code Geeks

zodream梦想开源/个人编程日记

文件解析笔记-zodream梦想开源/个人编程日记 密码本开发笔记之读写与保存-zodream梦想开源/个人编程日记 SkiaSharp 把 pixel byte[] 转成 SKBitmap-zodream梦想开源/个人编程日记 nas 使用 Docker 安装 gogs-zodream梦想开源/个人编程日记 复制 android 手机中的文件到电脑-zodream梦想开源/个人编程日记 周报:寻找优质的周刊-zodream梦想开源/个人编程日记 开发日志:对Markdown的代码块新增引用来源支持-zodream梦想开源/个人编程日记 周报:怎么写技术类的教程文章-zodream梦想开源/个人编程日记 css display:flex 布局尺寸超出问题-zodream梦想开源/个人编程日记 周报:SEO优化的思考-zodream梦想开源/个人编程日记 Edge 浏览器不适用 Edge Image Viewer 打开图片 -zodream梦想开源/个人编程日记 SEO 学习笔记(一) 内容来源-zodream梦想开源/个人编程日记 PHP 实现双因素身份认证(2FA)-zodream梦想开源/个人编程日记 WPF MVVM 获取List 多选数据-zodream梦想开源/个人编程日记 Burp Suite 抓包-zodream梦想开源/个人编程日记 使用 indexnow 注意事项-zodream梦想开源/个人编程日记 Godot 使用字体图标 例如: Iconfont、FontAwesome-zodream梦想开源/个人编程日记 angular 15 对指定页面进行访问限制-zodream梦想开源/个人编程日记 CSS 使用 column-count 实现瀑布流出现内容分割的解决办法-zodream梦想开源/个人编程日记 input 确认按键事件在手机端不生效-zodream梦想开源/个人编程日记 C# 使用socket 进行通讯-zodream梦想开源/个人编程日记 Maui开发中Windows应用开启管理员权限-zodream梦想开源/个人编程日记 Maui 中自定义控件-zodream梦想开源/个人编程日记 angular 14 使用 ng-template 实现tree 结构显示-zodream梦想开源/个人编程日记 c# 动态安装和卸载dll-zodream梦想开源/个人编程日记 慎用 CompositionTarget.Rendering-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:数据初始化-zodream梦想开源/个人编程日记 源码编译 aseprite-zodream梦想开源/个人编程日记 记录一下字符串分隔split各语言之间的不同-zodream梦想开源/个人编程日记 c# Gzip解码无头内容-zodream梦想开源/个人编程日记
c# 调用 c++ 的dll-zodream梦想开源/个人编程日记
zodream · 2021-09-19 · via zodream梦想开源/个人编程日记

c# 调用 c++ 的dll

c++ 程序的效率比 c# 的效率高很多

调用包含导出 c 函数的dll

第一步,新建“c++动态链接库”项目

第二步,添加方法

struct KeyItem
{
    std::uint32_t x, y, z;
};

extern "C" _declspec(dllexport) 
KeyItem FindKey(char* zipFile, char* zipFileName, char* plainFile, char* plainFileName)
{

}

12345678910

第三步,c#调用

复制 dll 到生成目录

[StructLayout(LayoutKind.Sequential)]
struct KeyItem
{
    public uint x, y, z;
}

public static class CrackerDLL 
{

    [DllImport("cracker.dll", EntryPoint = "FindKey", CallingConvention = CallingConvention.Cdecl)]
    internal static extern KeyItem FindKey(string zipFile, string zipFileName, string plainFile, string plainFileName);
}

123456789101112

第四步,使用


var res = CrackerDLL.FindKey("c.zip", "c.txt", "plain.zip", "plain.txt");

res.x
res.y
res.z

1234567

注意

生成平台必须选择一样的 x64x86,不能使用 Any CPU,否则会报错

调用导出 c++ 函数类的 dll

这种不是专门为跨语言调用生成的dll, 所有的导出函数名都进行了重新命名,不是原始名,因为 c++ 支持函数重载:即同一个函数名可以有不同的参数执行不同的过程


class __declspec(dllexport) MyClass
{
    public:
        MyClass(int count);
        static MyClass* Create(int count);

        MyClass Clone() const;
        MyClass* Copy();

        ColorClass Color;
}

1234567891011121314

c++ 类的编译规则

其实是分成两部分,一部分是数据(属性都保存在数据里),另一部分方法全都转成了静态方法存在在固定的位置

怎么获取对应函数的名称

最佳方法 ida pro 反编译 dll,然后就是可以在根据函数找到真正的名称

ida pro.PNG

调用类中的静态方法

[DllImport("cracker.dll", EntryPoint = "?Create@MyClass@filename")]
internal static extern nint Create(int count);

12

类的初始化

[DllImport("cracker.dll", EntryPoint = "??0class@filename")]
internal static extern void Construct(nint handle, int count);


var ptr = Marshal.AllocHGlobal(size); // 创建一个地址分配空间放数据
Construct(ptr, 1);  // 初始化

Marshal.FreeHGlobal(ptr);  // 记得手动释放

12345678

其中 size 是通过 c++ 调用 sizeof(MyClass) 获取的

类属性的赋值和获取值


var handle = ptr; // 类数据的指针
nint colorPtr = handle + colorOffset; 

// 就可以通过 colorPtr 获取和设置、调用 ColorClass 的值了

12345

colorOffset 是通过 c++ 调用 &((MyClass*)0)->Color 获取的

特殊的返回值

[DllImport("cracker.dll", EntryPoint = "Clone@class@filename")]
internal static extern nint Clone(nint handle, nint newHandle);

[DllImport("cracker.dll", EntryPoint = "Copy@class@filename")]
internal static extern nint Copy(nint handle);


var ptr = Marshal.AllocHGlobal(size); // 创建一个地址分配空间放数据
Construct(ptr, 1);  // 初始化

var ptr2 = Marshal.AllocHGlobal(size); // 创建一个地址分配空间放数据
Construct(ptr2, 1);  // 初始化

ptr2 = Clone(ptr, ptr2); // 返回的其实就是 ptr2 的指针

Marshal.FreeHGlobal(ptr2);  // 记得手动释放
Marshal.FreeHGlobal(ptr);  // 记得手动释放

1234567891011121314151617

当 C++ 调用方法返回值有引用和不是引用,

返回引用很好解决 MyClass* 直接写返回指针就行了

但是返回 MyClass const 就是麻烦了

ida pro 反编译可以看出实际必须调用前自己手动创建类,再把类的指针进去,当然返回了也是传的那个指针

转载请保留原文链接: https://zodream.cn/blog/id/221.html