调用c#程序集dll学习

By admin at 2021-07-03 • 0人收藏 • 652人看过

c#生成的dll不是c++那种动态库而是程序集, 调用方式不一样


首先, 先用c#创建一个dll, 命名为demodll , 创建三个函数, 

第一个 getg 是直接返回一个固定数值12345, 

第二个 getv 有一个参数, 然后返回这个参数值, 

第三个 swap 包含两个参数, 功能是交换这两个数值, 然后原路返回给这两个参数自己

c#代码如下:

namespace demodll
{
    public class Class1
    {
        public static bool swap(ref int a,ref int b)
        {
            a = a + b;
            b = a - b;
            a = a - b;
            return true;
        }
        public static int getv(int a)
        {
            return a;
        }
        public static int getg()
        {
            return 12345;
        }
    }
}

编译好的dll如下:

demodll.zip


下面在aardio中调用试试:

import console
console.open()

//调用C#程序集 
import dotNet; 
var appDomain = dotNet.clr().createAppDomain();
//加载应用程序目录下的程序集
var Demodll = appDomain.loadFile("\res\demodll.dll");
//声明接口
var class1 = Demodll.new("Class1")
//调用固定返回值函数
console.log( class1.getg() )
//调用返回参数值函数
console.log( class1.getv(6787) )

image.png

以上两个函数均能成功调用.


第三个参数, 因为参数是引用ref方式, 那么普通的方式肯定不行

var a =12;
var b =34;
console.log("原始顺序:",a,b);
console.log( class1.swap(a,b) );
console.log("交互后:",a,b);

image.png

虽然提示true成功了 , 但是并没有改变顺序, 这里既然是引用 , 那么应该需要对参数进行处理下, 我试了下topointer / raw.topointer / raw.struct 都不行.......


有谁知道怎么处理的, 请指教下


4 个回复 | 最后更新于 2021-07-17
2021-07-04   #1

目前有两种方案 :

  1. 用c#重新封装下那个函数, 把ref或out关键字的输出参数展开

    这里也有两个方案:

    a, 类里定义多个全局变量, 把ref参数用全局传递出来

    b, 用数组(int[])包装下, 给return返回出来

  2. 用dnspy查看dll中源码, 直接修改里面函数返回值 , 修改方法参考1


这里还是以上面的dll为例, 假如我把c#的swap函数代码改如下:

public static int[] swap(int x,int y)
{
    return new int[2] { y,x};
}

aardio调用如下:

var a =12;
var b =34;

console.log("原始顺序:",a,b);
console.dump( class1.swap(a,b) );

image.png

2021-07-04   #2

第二个方法演示, 利用dnspy直接修改dll中方法

  1. 打开dnspy ,拖动dll到左侧列表中

    image.png

  2. 点击class1类名, 右边可以看到里面的代码, 在代码界面 点击鼠标右键->编辑类 , 修改如下, 然后点击编译

    image.png

  3. 编译完成, 点击保存, 选择保存路径即可.

  4. 测试在aardio中调用

    结果同楼上.

2021-07-04   #3

c#与aardio进行数组交互


关于参数类型问题:

普通 C#函数不支持 COM接口的参数类型自动转换,如果默认类型转换与 C# 函数的参数类型不一致,可以使用 com.Variant(v,3/*_VT_I4*/)  或者com.SafeArray(3/*_VT_I4*/,12,34,56)这种方式显示的指定调用参数的类型。也可以使用 aardio 新版提供的函数 com.int8,com.int32,com.double …… 等,这些函数可以用于数值也可以用于数组,例如 com.int32({1,2,3}) 可以兼容 C# 的 System.Int32 数组。


这里需要注意一点: aardio中table表, 如果直接传递给c#参数, 是会被默认转换为double[]类型,  如果是其他类型数据, 那么可以利用上面提到的方式来定义

这时候我把c#的代码改下:

public static int[] test( double[] a,  double[] b)
{
     int x = (int)a[0] + 33;
     int y = (int)a[1] + 55;
     int z = (int)b[0] + 77;
     int u = (int)b[1] + 100;
     return new int[4] { x,y,z,u };
}

编译为dll之后, 在aardio中调用

console.dump( class1.test({11,22}, {33,44}) );

image.png

可以了.

2021-07-17   #4

这个不错,这样搞定排序问题。学习了。

登录后方可回帖

登 录
信息栏
公告:
个人博客
专注分享
谢谢合作!

本站域名:HtmLayout.Cn
aardio可以快速开发上位机,本站主要记录了学习过程中遇到的问题和解决办法及aardio代码分享

这里主要专注于aardio学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.

Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
本 站 主 站:Stm32cube中文网
Sciter中文在线文档Sciter在线学习文档
空间赞助:才仁机械
打赏本站
Loading...