MONO 如何打包 .NET程序独立运行(winform篇)13 重忆C 之 工程支出命令。

.NET程序独立运转是乘运行.NET的计算机上,不待安装.NET框架。

pwd
回了彻底目录

.NET程序集“独立运作”并非真的的独,它是运作在mono运行时基础之上的。由于此运行时方可独立存在,所以,我们不欲以目标机上安装.NET框架。

这时看到网返回了一个 /,这个 / 被我们称为系统的
根目录(root),这个职务吗即是我们现在在系受之职位。

图片 1

可是,我们要拓展工作之职的路也:

 

/home/user/project

 

据此,我们只要学会如何切换我们无处的职位:

如上图:

输入 cd 命令,并以 cd 命令后增长空格,在后输入进行工作之岗位的路径:

 

cd /home/user/project

同一,嵌入或不嵌入.NET程序集的故C/C++语言写的主程序,这个主程序负责对mono运行时进行操作。同时还只是配合.NET完成其余的天职(比如提供函数供.NET使用);

当下就算是一个层级化路径,其实那可透过

 

cd home
cd user
cd project

仲,mono的.NET运行时,这是一个动态库文件(mono以提供了静态库),是.NET程序集运行的第一条件。

逐次到达。

 

下载输入 ls -l。
这里就有个old目录。

其三,MONO运行时的配备文件要文件夹(并不一定需要)。

图片 2

 

image.png

季,外部的次第集并未内置到C程序中之另外的互动关.NET程序集。

mv main.c old             //mv [选项] 源文件或目录 目标文件或目录

“独立运作”的历程是:

双重下移动操作:

C语言通过mono提供的运作时api,调用mono运行时有关函数,通过mono运行时加载并运行.NET程序。

图片 3

 

移步文件

即:

重新创新文件,通过命令

C语言程序(your.exe)
–à mono的.NET运行时(libmonosgen-2.0.dll) –à .NET程序集

touch main.c 

 

始建新文件
这儿可以瞥见:

libmonosgen-2.0.dll,即是.NET程序集的运行规范,也是.NET程序集和C程序之间数据交流、函数互调的大桥。

图片 4

吓了,有矣上述之理论知识,下面我们便开实践一下咔嚓

创立文件

 

old目下把key删除

1.利用Xbuid命令编译

图片 5

图片 6

删除“`key“`文件

 

又多系命令的但叠加参数与动意义,可以经
man [空格] [命令名]的计开展拓展进一步的询问(查询后离只需要敲击键盘上之
q 即可)。

2.将编译后的net 运行文件 写副到一个 char[]变量中,并记下这序集的称谓,大小

双重多复杂的通令,点击这里

mkpack H:\Csharp\Mono\Test\TestBuild\TestBuild\WindowsFormsApplication1\bin\Debug\WindowsFormsApplication1.exe

大抵模块程序

前面的课中,所有文件操作都是就文件进行。对于一个止完成一个一定的任务,只含有十几个函数的程序来说,单文件的团组织办法还算是好承受,但是当次更加长,程序实现的效用越来越多,将她们所有还组织于一个文书里便会转换得无那么好给人收受了。

因此,我们用上学怎么样以 C
语言中将不同作用于差不多只代码文件被分头实现,然后以它作为多只模块组织在齐吗跟一个顺序服务。


会生成3个文件

关于gcc命令

原地址:gcc命令中参数c和o混合使用的详解、弄清gcc test.c 与 gcc -c
test.c
的别

gcc命令使用GNU推出的冲C/C++的编译器,是开源代码领域采取最普遍的编译器,具有功能强大,编译代码支持性优化等特征。现在广大程序员都运GCC,怎样才能更好的使GCC。目前,GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的次第,可因需要选择设置支撑之语言。

语法

gcc(选项)(参数)

选项

-o:指定生成的输出文件;
-E:仅执行编译预处理;
-S:将C代码转换为汇编代码;
-wall:显示警告信息;
-c:仅执行编译操作,不开展连续操作。

参数

C源文件:指定C语言源代码文件。

实例
常用编译命令选项

借设源程序文件称吧test.c

无选项编译链接

gcc test.c

test.c先处理、汇编、编译并链接形成可执行文件。
此处不指定输出文件,默认输出为a.out

选项 -o

gcc test.c -o test

test.c先处理、汇编、编译并链接形成可执行文件test
-o选料用来指定输出文件的文书称。

选项 -E

gcc -E test.c -o test.i

拿test.c预处理输出test.i文件。

选项 -S

gcc -S test.i

用优先处理输出文件test.i汇编成test.s文件。
选项 -c

gcc -c test.s

以汇编输出文件test.s编译输出test.o文件。

无选项链接

gcc test.o -o test

以编译输出文件test.o链接成最终可执行文件test。

选项 -O

gcc -O1 test.c -o test

动编译优化级别1编译程序。级别为1~3,级别越充分优化作用更好,但编译时间越长。

多源文件之编译方法

万一起差不多单来自文件,基本上出零星种植编译方法:

设来些许单来自文件呢test.ctestfun.c

  • 差不多独公文共编译

gcc testfun.c test.c -o test

testfun.ctest.c个别编译后链接成test可执行文件。

  • 分级编译各个源文件,之后对编译后输出的目标文件链接。

gcc -c testfun.c

将testfun.c编译成testfun.o

gcc -c test.c

将test.c编译成test.o

gcc -o testfun.o test.o -o test

将testfun.o和test.o链接成test

上述两栽方法相较,第一中方法编译时需要具备文件再次编译,而第二种方法好独自更编译修改的文本,未修改的公文不用再行编译。


重复来复习一下:

gcc -c a.c 编译成靶子文件a.o

gcc -o a a.o 生成执行文书a.exe

gcc a.c 生成执行文书a.exe

gcc -o a -c a.c 编译成靶子文件a

gcc -o a a.c 生成执行文书a.exe

当a.c中援引test.c中的一个函数后:

gcc -c test.c 编译成靶子文件test.o

gcc -c a.c 编译成靶子文件a.o

gcc -o a test.o a.o 生成执行文书a.exe

gcc -o a test.o a.c 生成执行文书a.exe

gcc -o a test.c a.c 生成执行文书a.exe

gcc -o a test.o a.c 生成执行文书a.exe

总结:只要参数中产生-c,总是变目标文件;只要参数中无-c而只有-o,则连接变化执行文书。


以刚开修 C
语言的时候,我们曾经读书过,当我们的先后只发一个main.c文本时,我们得以于指令行中通过

gcc -o program main.c

本着单个代码文件进行编译,生成可执行文件program,并且经过./program运行编译生成的顺序。在咱们事先的课被,计蒜客的修系统吧拉您进行了如此的操作。

比叫单个文件、单一功能的主次,当次来差不多只模块时,问题即从头转移得复杂了。我们对每一个模块会率先编译出每个模块对应之*.o目标代码文件(relocatable
object file),例如:

gcc -c -o set.o set.c

会晤用我们的一个set.c文本编译成一个set.o的目标代码文件。请留心,这里的-c表示生成目标代码文件。-o与之前光文件的时刻同样,在它们之后我们见面刻画清楚于转移的文本之称号。

当我们就了每一个独模块的编译并获得它们的对象代码文件后,我们好拿我们的主程序的目标代码文件与她们链接以同步。例如:

gcc -o program main.o set.o others.o

将对象代码文件set.oothers.omain.o于链接以一道,并且输出了
可执行文件(excutable file)program。

我们依旧可经过./program运行编译生成的次第。

当我们将一个程序写在差不多只文本被时时,每一个文件中之变量和函数默认都是只有文件内的一部分才得看的。但是来局部奇特之全局变量、类型定义、函数可能会见需要以差不多个文件被被采用。

此时,我们得以用随即类的情单独写成一个 头文件(header
file),并且将全局变量、类型定义、函数声明写到头文件被。

对一个文本set.c,习惯及它们的条文件会被命名为set.h。在备需要因此set.h中全局变量、类型定义、声明的函数的文件被,用

#include "set.h"

将相应的头文件引入。在此地的引入头文件措施及引入系统库头文件之艺术非常相近,只不过这里用底凡引号""设若非是尖括号<>

是因为头文件里吧足以引入头文件,因此我们恐怕实际多次引入和一个文件,比如我们引1.h2.h,且1.h也引入2.h,这时坐2.h于引入了少不成,就产生或出现更的宣示。为了解决之题目,我们2.h中定义一个庞然大物,在2.h的卓绝开始判断这大是否让定义了,如果叫定义了,就逾了2.h全体文件的内容。

这里我们将会晤就此到少单新的事先处理指令#ifndef xxx#endif,它们变成对出现还#ifndef于前边,作用是使这并未曾定义xxx宏,则这对#ifndef xxx,
#endif以内的情使得。(其中xxx好轮换为随意宏名)

这样```2.h```可以写为类似于如下的内容:
#ifndef xxx
#define xxx
typedef enum Status { Success, Fail };
typedef struct {
    char *name;
    int age;
} People;
Status go_to_Jisuanke(People);
#endif

细心之同室已发现,如果当先后中从来不引入2.h的职位定义了xxx宏,则#include "2.h"丁之扬言并无见面吃引入,因此我们无应当当这以xxx这种平凡的名。实际上,我们一般会利用一个同峰文件称系的名字来代替xxx,比如一个常用之代码风格里,这个庞然大物的讳形式也工程名_路径名_文件名_H_

图片 7

总结的几沾

  • 某个同代码中定义的函数如果欲为外代码文件所采用,应该用函数的扬言放入头文件,并在其他代码文件中引入这同一峰文件。
  • 并不需要把每个函数单独写成一个模块,还是应该因效益的分割与贯彻去控制怎么抽出模块。
  • 足只有多只.c的文本,也并不一定非要是还拆出.h文件。
  • #include可以吃用于引入系统库头文件为足以给用于引入自己实现之峰文件。
  • 只不过在引入系统库头文件时,我们数会下尖括号<>,而于引入自己实现的峰文件时一般用引号""
  • gcc时,-o日后写的是生成可执行文件的称呼。-c的参数的以会拉扯咱得一个靶文件。

//-c和-o都是gcc编译器的可选参数

//-c表示只编译(compile)源文件但不链接,会把.c或.cc的c源程序编译成目标文件,一般是.o文件。
//-o用于指定输出(out)文件名。不用-o的话,一般会在当前文件夹下生成默认的a.out文件作为可执行程序。

//例如
gcc -c test.c          //将生成test.o的目标文件
gcc -o app test.c           //将生成可执行程序app

gcc -c a.c -o a.o          //表示把源文件a.c编译成指定文件名a.o的中间目标文件(其实在这里,你把-o a.o省掉,效果是一样的,因为中间文件默认与源文件同名,只是后缀变化)。

data.c 是.NET程序集的二进制内容

Makefile

于前方学习多模块程序的上,我们要事先管每个模块的代码都非常成为目标代码文件,然后又用目标代码文件联编成一个可执行文件。如果各国一样糟编译都使输入这么多命令,是未是颇复杂呢?如果老是修改一点点内容就是需再行编译整个工程,是匪是深浪费时间呢?

为了缓解所碰到的问题,方便开发,我们采用一个号称make的吩咐,它可以读取Makefile文件,并且根据Makefile遭遇之规则描述把源文件特别成为可实施之先后文件。

极致基本的Makefile中寓了相同文山会海形式如下的平整。请小心,每一样长条规则之通令前,必须要发出一个制表符\t。

目标: 依赖1 依赖2 ...
    命令

比如说,可以描绘一修规则:

array.o: array.c array.h
   gcc -c -o array.o array.c

代表生成的文件是目标代码文件array.o,它依靠让array.carray.h
当我们以指令行中执行make array.o时不时,根据这同一条条框框,如果array.o无设有或者array.carray.h足足有比array.o履新,就会实行gcc -c -o array.o array.c

俺们拿上述代码保存也Makefile,与array.carray.h位于同样目录,在非常目录里实行make array.o不畏能收看效果。

注意:Makefile里的除了当前目录隐藏文件外之首先独对象会成为运行make匪指定目标时的默认目标。

再看:

main: array.o main.o
    gcc -o main array.o main.o

main.o: main.c array.h
    gcc -c -o main.o main.c

array.o: array.c array.h
    gcc -c -o array.o array.c

Makefile发差不多长规则时,如果我们盼望就特别成中一个,我们得以make命令后增长要变更的目标的名。例如,在此我们得实行make main.omake array.omake main。当我们执行make main时,make命令发现array.omain.o勿有,就见面因盖它们为对象的条条框框先生化作它。

众时节,会要将.o为后缀的对象代码文件和而尽之先后文件去,完全从头进行编译。那么我们好描绘一条clean规则,例如:

clean:
    rm -f array.o main.o main

rm命令表示去文件,-f代表强制,因此rm -f array.o main.o main

按照预期,当我们尽make clean即得去除array.omain.omain了。事实真的这么吧?

以毕竟这如就是clean文件,rm一声令下就无见面实施了。为了化解之题目,我们经过一个奇异的道告诉make以此号称吧clean的平整以clean存在的时段还是有效。

.PHONY: clean

clean:
    rm -f array.o main.o main

.PHONY用来声明一些黑目标,伪目标和一般的目标的基本点区别是地下目标不见面让检查是否在被文件系统中要默认不存都无见面用默认规则变更它。

当Makefile中我们还好用它们的变量和注释。

# 井号开头的行是一个注释
# 设置 C 语言的编译器
CC = gcc

# -g 增加调试信息
# -Wall 打开大部分警告信息
CFLAGS = -g -Wall

# 整理一下 main 依赖哪些目标文件
MAINOBJS = main.o array.o

.PHONY: clean

main: $(MAINOBJS)
    $(CC) $(CFLAGS) -o main $(MAINOBJS)

array.o: array.c array.h
    $(CC) $(CFLAGS) -c -o array.o array.c

main.o: main.c array.h
    $(CC) $(CFLAGS) -c -o main.o main.c

clean:
    rm -f $(MAINOBJS) main

方这事例已经是一个比较完整的Makefile了。以#始发的是我们的注释,我们于此用注释说明了俺们定义之Makefile变量的用处。CC变量定义了编译器,CFLAGS变量标记了编译参数,MAINOBJS变量记录了main拄的靶子文件。定义的变量可以一直通过$(变量名)拓展下。

data_.c 是以文件用户调用的对data.c的函数和变量

总结

  • 一个 Makefile
    可以分包多只规则,我们既然可以每次在make后证履行哪个意义,也得经定义之all来施行同样多样之条条框框。
  • 于为此gcc编译时加上-Wall会显示错误信息,Wall是用于展示多数警告信息之,编译错误信息默认就会见来得。
  • Makefile其实描述了千篇一律密密麻麻转为对象文件、联编的经过,不采用make也是可得的。
  • Makefile中的变量是用$()的点子来之所以哒。

data.h  是data_.c的头文件,是用户c源码必须的。

Makefile体验

图片 8

(1)

→ ~/project ls -l                                                                                 

total 16                                                                                          
-rw-r--r-- 1 user user 304 Sep 15 16:46 array.c                                                   
-rw-r--r-- 1 user user  87 Sep 15 16:46 array.h                                                   
-rw-r--r-- 1 user user 297 Sep 15 16:46 main.c                                                    
-rw-r--r-- 1 user user   0 Sep 15 16:46 main.h                                                    
-rw-r--r-- 1 user user 419 Sep 15 16:46 Makefile                                                  
→ ~/project                                                                                       
→ ~/project cat Makefile                                                                          

# 设置 C 语言的编译器                                                                             
CC = gcc                                                                                          

# -g 增加调试信息                                                                                 
# -Wall 打开大部分警告信息                                                                        
CFLAGS = -g -Wall                                                                                 

# 整理一下 main 依赖哪些目标文件                                                                  
MAINOBJS = main.o array.o                                                                         

.PHONY: clean                                                                                     

main: $(MAINOBJS)                                                                                 
        $(CC) $(CFLAGS) -o main $(MAINOBJS)                                                       

array.o: array.c array.h                                                                          
        $(CC) $(CFLAGS) -c -o array.o array.c                                                     

main.o: main.c array.h                                                                            
        $(CC) $(CFLAGS) -c -o main.o main.c                                                       

clean:                                                                                            
        rm -f $(MAINOBJS) main                                                                    
→ ~/project                                                                                      

图片 9

(2)

→ ~/project make                

gcc -g -Wall -c -o main.o main.c                                                  
gcc -g -Wall -c -o array.o array.c                                    
gcc -g -Wall -o main main.o array.o                                     
→ ~/project                               

图片 10

(3)

→ ~/project ./main              

1 2 3 4 5 6 7 8 9 0                                     
数组元素和为: 45                                             
数组元素平均值为: 4.5                                      

→ ~/project                                                 

图片 11

(4)

→ ~/project make clean                   

rm -f main.o array.o main             

图片 12

(5)

→ ~/project            
→ ~/project ls -l     

total 16                                             
-rw-r--r-- 1 user user 304 Sep 15 16:46 array.c          

 

命执行参数

之前,main函数一般还未曾参数,对许在运转时,一般就是直接输入而尽之主次文件称(例如./main)。

唯独事实上main函数可以发参数。我们得以用其余过去不管参数的main函数替换成下面这种产生参数的main函数(不过考虑到我们连无动,不写是死正常的)。

int main(int argc, char **argv) {
    // ...
}

在这里,main函数有个别只参数,第一独参数是整数型,会传命令执行参数的个数,程序运行时就是可以接到及。第二只参数是char **,其中蕴藏了用户从命执行传递进入的参数。

设我们的主次可执行文件名也main,则以指令执行遭输入./main hello world咱俩会落argc3argv[0]./mainargv[1]helloargv[2]world。如果起双重多参数为得以为此类推。

指令执行参数默认都是空格分隔,但是一旦我们期待包含空格的一个字符串作为参数,我们虽要在输入参数时用引号将那个包装起来。

万一我们的次序可执行文件名也main,则于指令执行被输入./main "hello world" is my greet咱会得argc5argv[0]./mainargv[1]hello worldargv[2]isargv[3]myargv[4]greet

其余被接受到的argv参数还足以吃视作正常的字符串在代码里采取。在重重程序的规划着,我们见面待基于接收到的参数来控制程序的尽办法,这时候,学会运用argcargv尽管展示格外重点了。在此后的学科中,你吧会用利用当下无异片的文化,一定要学明白喔。

3.用编译data.c编译为对象文件data.o

一部分总结

  • 命令执行读入的参数是于命行键入的可执行程序路径始于算。
  • 于main函数中用于接收命令行参数的函数参数中,第一只凡是命令执行参数的个数。
  • 在int main(int argc, char **argv)中,argc就定位啊 2
    了,它获到的应有是令执行中键入的参数只数。

gcc -c -o data.o data.c

指令执行参数

令执行参数是怎么抱和使用的?

伸手先输入 cat main.c 看一下咱们目前所于目录下之 main.c 文件。

图片 13

image.png

观看,在此 main.c 的公文中,我们的 main 函数获取了指令执行参数的个数
argc(整数型)和平等多样参数(字符指针的指针,可以为此拜访数组的花样拜访)。

是序用预期输出命令执行参数的多寡,并且将各国一个参数逐一列出。
连通下去给我们 make 一下,完成对这个顺序的编译。

图片 14

image.png

完成了 make,就受咱们把它运行起来吧。请输入 ./main
并运行起来是顺序,并当此后自由输上有空格分隔开的字符串,例如:

./main I feel better after this

俺们先后中之argc
接受到的参数一共是几乎单,它们各自对应了咱们当极限中输入的呀有底情节也。

图片 15

image.png

 

文件操作

之前课程中,我们读、设计之兼具程序还是从业内输入进行读取、向专业输出进行摹写来底,操作系统也咱准备好了业内输入、标准输出的界面。在当下节课中,我们即将学习怎么样从文本中开展读取、如何为文件进行写入。

于朗诵文件之上我们用先出一个得给我们走访到文件之 文件指针(file
pointer),它是一个FILE品种的指针。

咱们得经下的法宣示一个文件指针。

FILE *fp;

此刻,如果我们盼望对一个文本进行操作,我们得先用

fp = fopen(文件路径, 访问模式);

以文件指针和文书涉及起来,其中第一个参数是一个字符串,对诺了咱们想看的公文路径。第二单参数是看模式,它可以是表示无非读模式之"r",也堪是意味无非写模式的"w",还好是以文书末尾追加的"a"

当我们将文件指针和文件涉及起来后,我们就是足以经fgetc(fp);获得当前指针之后位置的一个字符了,每获得一个字符,指针会向后移动一个字符(如果达文件尾则会回去EOF)。

俺们这通过fputc('c', fp);的方式以字符'c'写入到fp涉及的文书内了。

刺探及这些信后,我们便足以实现用一个文书复制到外一个文件内之函数了,例如:

void filecopy(FILE *in_fp, FILE *out_fp) {
    char ch;
    while ((ch = fgetc(in_fp)) != EOF) {
        fputc(ch, out_fp);
    }
}

以此函数接收的蝇头个参数还是文件指针。这个函数会通过一个只是读模式之文件指针逐字符地读取,并且经过一个而写模式之公文指针逐字符地将拥有字符写有,从而从至复制文件内容之意向。

公用注意,在叫文件指针进行命名的当儿,要逃避 stdin、stdout 和 stderr
这三只称呼。因为就三个号其实就用于规范输入、标准输出、标准错误的公文指针。

而也许会见咨询了,那咱们看看底 stdinstdout
stderr的即时三独文件指针可以直接利用呢?回答是毫无疑问的。

我们是经过
fgetc(stdin);抱来自专业输入的字符,也可通过fputc(ch, stdout);
fputc(ch, stderr);将变量 ch受到的字符输出及专业输出或专业错误被之。

除此之外fgetc和fputc之外,我们尚足以采取fscanf和fprintf函数。这简单只函数都深像咱就非常熟稔的scanf和printf函数,只是不过,scanf和printf
可以吃视作 fscanf和fprintf 的特例。

咱采用 fscanf 从文本指针in_fp进行读取时,可以写成:

fscanf(in_fp, "%c", &a);

假若如果我们形容

fscanf(stdin, "%c", &a);

立将完全和下直接行使 scanf 的办法相当。

scanf("%c", &a);

恍如地,我们下fprintf向文件指针out_fp进行摹写有时,可以描绘成:

fprintf(out_fp, "%c", a);

要设我们写

fprintf(stdout, "%c", a);

及时将全同下部直接下 printf的方法等。

printf("%c", a);

以动文件同时确定不再接续使用后,我们设经过下面所显示之方拿文件指针fp与公事之涉嫌断开。你得将它们视为与fopen反倒的一个操作。

fclose(fp);

要是您不在次中应用fclose,程序正常化了时,程序会为富有打开的文本调用fclose

stdinstdout实则呢是受辟的公文指针,如果你认为之所以非顶之语句,其实呢是可以运用fclose用他们关闭掉的。你可协调尝试一跃跃欲试,关闭
stdinstdout 会对我们以前写了之程序带来什么的影响啊?

4.将编译data_.c编译为目标文件data_.o

gcc -c -o data_.o data_.c -IC:/mono-3.2.3/include/mono-2.0

 

5.将data.o和data_.o 合成为一个纯粹的静态库:data.a

ar rcs data.a data_.o data.o

 

6.编译test.c和连接data.a,生成 test.exe

gcc -o output\test.exe test.c data.a %GCC_OPT% -lmonosgen-2.0

 

末了的硕果如下

图片 16

 

winform 最中心的 lib 有以下几独,添加到lib\mono\gac目录下。

图片 17

 

运行试试,没有问题

图片 18

 

那极端关注的政工来了。

本条文件于包了mono的.net 运行时,size有多不胜也?

图片 19

 

削减一下

图片 20

 

对待传统的由包.net 运行时 这该是一个可怜令人满意的尝尝吧,结束!

 

图片 21

编译后底顺序:图片 22

 

 

使大家认为有需要,下篇文章我会写什么的部署 打包环境。

相关文章

admin

网站地图xml地图