第一部分:产生C的dll
1、 1,新建win32工程,选中DLL项目,如下图:
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窗口中,更改其
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();
}
}
|
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
|
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;
}
}
|
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
|