调用c#程序集dll学习

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

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 都不行.......


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


11 个回复 | 最后更新于 2023-09-21
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

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

调用dll这块,我研究了一个多月,都没研究明白,看了不下十个帖子。。。。。

2023-07-27   #6

回复#5 @鸿湖重工业株式会社 :

首先你最好要对c#有一定的了解, 知道程序集的定义和引用方式, 知道名字空间和类这些方法的使用, 要不然两眼抹黑会抓瞎

你可以研究下论坛里这些调用波形图c#dll的帖子, 多和c#写法对比就知道咋弄了.

回复#6 @admin :

谢谢指点。我花了较长的时间,现在学会调用scottplot那个库了,还有zedGraph,oxyplot这两个控件也都学会调用了。

只是有一些命令仍然无法成功调用,主要是不知道调用里面函数的逻辑是什么,一直都是在不断的试错,尝试。

我对比下aardio和C#的写法,再去总结下。谢谢

2023-09-01   #8

回复#7 @鸿湖重工业株式会社 :

因为scottplot、ZedGraph、oxyplot这些都是C#的库,在C#中用Nuget引入后会有比较详细的代码提示,所以一般直接在VS中就能看到应该调用什么函数实现什么功能,但在aardio中是无法直接看到的,一个一个试错的效率实在是太低了。

比较好的做法是现在VS中学会如何使用,然后再在aardio进行同样逻辑的调用,这样可以少走不少弯路。

回复#8 @jerryxjr1220 :

您说的太对了。我在aar中加载dll,使用的时候,没有属性或方法的提示,也就是说,得试错,通过错误代码去分析,我也会使用spy去看那个dll都有哪些方法,但效率还是很低,不断试错中。

请问这个Nuget是什么? 该如何使用?

2023-09-21   #10

回复#9 @鸿湖重工业株式会社 :

nuget 包管理工具

2023-09-21   #11

回复#9 @鸿湖重工业株式会社 :

Nuget是Visual Studio的默认包管理工具,装了Visual Studio就自带了

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...