VS2010产生C的dll方法和C#调用方式

第一部分:产生C的dll

 
1、 1,新建win32工程,选中DLL项目,如下图:
VS2010产生C的dll方法和C#调用方式_第1张图片
2,分别添加头文件和cpp文件

?
1
2
3
4
5
6
7
// CDLL.h头文件
#ifndef LIB_H
#define LIB_H
extern "C" _declspec( dllexport ) int add( int x, int y);    // 声明为C编译、链接方式的外部函数
extern "C" _declspec( dllexport ) int sub( int x, int y);    // 声明为C编译、链接方式的外部函数
/* 加入任意你想加入的函数定义*/
#endif
?
1
2
3
4
5
6
7
8
9
10
11
12
13
// CDLL.cpp文件
#include "stdafx.h"
#include "CDLL.h"//貌似这两个头文件的顺序不能颠倒。我试了很多次,但是不能确定。
 
int add( int x, int y) //是否可以理解为,VS2010已经默认是 _stdcall,所以函数不用添加该修饰符
{
     return x+y;
}
 
int sub( int x, int y)
{
     return x-y;
}


//上面的代码可能会导致
error C2059: syntax error : 'string'  
的问题。借鉴网上的提供的经验http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/eb89a44d-35cb-4ad0-88ce-cf9664c9fcbc。说法很混乱。但经过本人的调试,发现如果是正常的C++的编译连接器,则不会出现问题。如果对应的是 CDLL.c文件,不是CDLL.cpp文件,可能出现上述问题。
如果跟CDLL.c文件,则改为下面形式,不会出现error c2059:syntax error:'string' 

?
1
2
extern _declspec( dllexport ) int add( int x, int y);    // 声明为C编译、链接方式的外部函数
extern _declspec( dllexport ) int sub( int x, int y);    // 声明为C编译、链接方式的外部函数
暂时还没有发现其他问题。 

3,按F6编译,在相应的Debug文件夹里面可以找到生成的.dll文件。

第二部分:C#调用方式dll


1,建立一个工程,然后在SolutionExplorer窗口,选中需要动态链接库(DLL)的工程(project),右击添加已有文件,选择上面生成的.dll文件,然后加入到工程中来。
2,在SolutionExplorer窗口,选中该文件,在下面Properties窗口中,更改其

VS2010产生C的dll方法和C#调用方式_第2张图片

3,在C#程序中加入如下代码,就可以使用了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Program
     {
         //下面的语句解决问题的说明见
         // http://blog.csdn.net/xuehuic/article/details/7682793
         [DllImport( "CDLL.dll" , CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
         extern static int add( int a, int b);
 
         [DllImport( "CDLL.dll" , CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
         extern static int sub( int a, int b);
 
         static void Main( string [] args)
         {
             Console.WriteLine(add(10, 2).ToString());
             Console.WriteLine(sub(10, 2).ToString());
             Console.Read();
         }
     }
第三部分:把一般的可执行C,CPP改为dll

1、为了便于改下已经存在的c或者cpp项目,可以按照第一部分的做法先新建一个.dll工程。便于下面修改代码。假设新建的.dll动态库的工程为NewDll,待改动的C或CPP工程为OldC,下面以修改某个GSM_AMR算法为.dll动态链接库作例子,说明过程。

2、用VS2010打开OldC,右击OldC工程,添加已存在文件,找到NewDll文件夹里面的dllmain.cpp文件,按F6,如果报错,看缺少那些头文件。一般BOOL被报错,说明缺少stdax.h等,一直添加NewDll工程里面的头文件,直至可能提醒可能#include “XXXX.h”不存在。一般这是由于该头文件和其他头文件不在同一个目录下,可以将他们调整到同一个目录下面。

3、右击OldC工程的Properties属性,打开,修改输出类型为DLL,而不是.exe文件。这个可以自己慢慢找,总会找到的,一般打开的窗口就是可以修改输出类型的。

4、按F10找到OldC的主函数main(),一般main()所在的文件都没有对应的头文件。可以为他建立一个同名头文件,按照第一部分里面的说明,把main()函数里面的头文件都复制到该同名头文件里,然后添加第一部分的代码CDLL.h里面的如下代码。

?
1
2
3
4
5
6
7
// CDLL.h头文件
#ifndef LIB_H
#define LIB_H
extern "C" _declspec( dllexport ) int add( int x, int y);    // 声明为C编译、链接方式的外部函数
extern "C" _declspec( dllexport ) int sub( int x, int y);    // 声明为C编译、链接方式的外部函数
/* 加入任意你想加入的函数定义*/
#endif
修改成你想要的函数格式。

5、在main()所在的文件里面添加你所需要的函数体。

6,按F6,应该出现Build success,如果出现什么问题,极有可能是上面第一部分提的那个问题,可以按照上面的方式解决。生成的.dll文件,可以到相应的Debug里面去找。

第四部分:手把手教你把C语言的MELP语音压缩算法改为dll形式

1、首先网上搜索melp C,可以下载到美国军方标准的MELP开源的C代码。具体网址就不提供了。

2、打开VS2010(我的是英文版的),New Project->选择VisualC++的win32 project,余下的部分就和第一部分有点重复了。本文的工程名字:FileMelp

3、由于阅读了该源代码很多次了,了解了MELP算法的结构,以及帧的结构。编写了几个函数,方便调用。

4、回到第2步,右击工程名字,添加已有文件,把MELP解压缩后的文件都添加进来。

5、在melp.h文件最底部,加入如下的头部,方便生成dll的函数头部。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef LIB_H
#define LIB_H
 
extern _declspec( dllexport ) void cmd_melp( int argc, char **argv);
 
 
extern _declspec( dllexport ) void melp_encoder_ini();
 
extern _declspec( dllexport ) void melp_encoder(
     short speechIn720[],
     char result27[]);
 
extern _declspec( dllexport ) void melp_encoder720s(
     short speechIn720s[], //best length=720
     int times,
     char result27s[]);
 
     
extern _declspec( dllexport ) void melp_decoder_ini();
extern _declspec( dllexport ) void melp_decoder(
     char inChar27[],
     short *speechOut720);
extern _declspec( dllexport ) void melp_decoder27s(
     char inChar27s[],
     int times,
     short *speechOut720s);
 
/* 加入任意你想加入的函数定义*/
#endif
6、在melp.c的最底部,加入如下的函数体。 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
void cmd_melp( int argc, char **argv)
{
     main(argc,argv);
}
 
 
void byte36Tobyte27( char * in36, char *out27)
{
     /* because 6 bits of a byte was used, so we can delete such bits.
     do as follow:
     the first 3*9 bytes was the original bytes.
     the last 1*9 bytes,was adding to the head*/
     char *in=in36;
     char inTem;
     char *out=out27;
 
     /* copy the 3*9 bytes */
     int n=27;
     while (n--)
     {
         *out++=*in++;
     }
 
     /* return the output*/
     out=out27;
     n=9;
     while (n--)
     {
         inTem=*in++;
         *out=(*out)|((inTem&0x30)<<2);
         out++;
         *out=(*out)|((inTem&0x0C)<<4);
         out++;
         *out=(*out)|((inTem&0x03)<<6);
         out++;
     }
}
 
void byte27Tobyte36( char * in27, char *out36)
{
         /* because 6 bits of a byte was used, so we can delete such bits.
     do as follow:
     the first 3*9 bytes was the original bytes.
     the last 1*9 bytes,was adding to the head*/
     char *in=in27;
     char inTem;
     char *out=out36;
 
     /* copy the 3*9 bytes */
     int n=27;
     while (n--)
     {
         *out++=((*in++)&0x3F); //because the first 2 bits was useless,so we can preserve
     }
 
     /* return the output*/
     in=in27;
     n=9;
     while (n--)
     {
         inTem=(*in++)&0xC0;
         *out=0;
         *out=inTem>>2;
         inTem=(*in++)&0xC0;
         *out=(*out)|(inTem>>4);
 
         inTem=(*in++)&0xC0;
         *out=(*out)|(inTem>>6);
         out++;
     }
}
 
void melp_encoder_ini()
{
     melp_ana_init();
}
 
void melp_encoder(
     short speechIn720[], //best length=720
     char result27[])
{
     /*
     here we assume that the LengthSpeechIn%180=0;
     */
 
     static struct melp_param melp_par;      /* melp parameters */
     unsigned int chbuf[CHSIZE];
     char bytes36[36];
     float speechIn180[180];
     int LengthSpeech=180;
     int LengthByte=9;
     short * inOriginal;
     float * in180;
     char *out36byte;
     int q=4;
 
 
     inOriginal=speechIn720;
     out36byte=bytes36;
 
     while (q--)
     {
         /* copy the original speech into speechIn180 */
         LengthSpeech=180;
         in180=speechIn180;
         while (LengthSpeech--)
         {
             *in180++=*inOriginal++;
         }
 
         melp_par.chptr=chbuf;
         melp_par.chbit=0;
 
         /* do melp_ana */
         melp_ana(speechIn180,&melp_par);
 
 
         /* copy out */
         LengthByte=9;
         melp_par.chptr=chbuf;
         chbuf[0]=chbuf[0]-0x8000;
         while (LengthByte--)
         {
             *out36byte++=*(melp_par.chptr++);
         }
     }
 
     /* because only 6bits of a byte was used, so we can delete such usless bits. */
     byte36Tobyte27(bytes36,result27);
 
}
 
 
 
void melp_encoder720s(
     short speechIn720s[], //best length=720
     int times,
     char result27s[])
{
         
     short *in=speechIn720s;
     char *out=result27s;
     int i=times;
     while (i--)
     {
         melp_encoder(in,out);
         in+=720;
         out+=27;
     }
}
 
void melp_decoder_ini()
{
     melp_syn_init();
}
 
void melp_decoder(
     char inChar27[],
     short *speechOut720) //best length=180;else the same)
{
 
     static struct melp_param melp_par;      /* melp parameters */
     unsigned int chbuf[CHSIZE];
     char inChar36[36];
     float speechOut180[180];
     int LengthSpeech=180;
     int LengthBit=9;
     short * OutOriginal;
     float * Out180;
     unsigned int *in9s;
     char *inOriginal;
 
     int q=4;
 
     byte27Tobyte36(inChar27,inChar36);
     inOriginal=inChar36;
     OutOriginal=speechOut720;
 
     while (q--)
     {
         /* copy the original speech into speechIn180 */
         LengthBit=9;
         in9s=chbuf;
         while (LengthBit--)
         {
             *in9s++=*inOriginal++;
         }
 
         melp_par.chptr=chbuf;
         melp_par.chbit=0;
         chbuf[0]=chbuf[0]+0x8000;
         /* do melp_syn */
         melp_syn(&melp_par,speechOut180);
 
 
         /* copy out */
         LengthSpeech=180;
         Out180=speechOut180;
         while (LengthSpeech--)
         {
             *OutOriginal++=*Out180++;
         }
     }
 
}
 
 
 
/*  解码27长度的倍数 */
void melp_decoder27s(
     char inChar27s[],
     int times,
     short *speechOut720s)
{
     char *in=inChar27s;
     short *out=speechOut720s;
     int i=times;
     while (i--)
     {
         melp_decoder(in,out);
         in+=27;
         out+=720;
     }
}
实现相应的功能,同时要调整melp.h在melp.c中的位置,一般是在那一堆.h文件中,放置到最后面一行。

7、调试dll代码的过程,可以参加我上面的博客。生成后代码,就可以用在你想要的C#里面了。我在C#里面调用的方式如下。其中生成的FileMelp.dll改成了Melp.dll名字,如何添加到C#部分,详细见上面的部分。这样就可以运行了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#region 需要的外部函数
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_encoder_ini();
 
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_encoder(
     Int16[] speechIn720,
     byte [] result27
     );
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_encoder720s(
     Int16[] speechIn720s,
     int times,
     byte [] result27s
     );
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_decoder_ini();
 
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_decoder(
     byte [] in27,
     Int16[] speechOut720
     );
 
[DllImport( "Melp.dll" , CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static void melp_decoder27s(
     byte [] in27s,
     int times,
     Int16[] speechOut720s
     );
#endregion

分享 

你可能感兴趣的:(VS2010产生C的dll方法和C#调用方式)