第一部分:產生C的dll html
http://210.43.24.222/chy/3sbase/news/?766.html(資料來源,有改動)
一、 1,新建win32工程,選中DLL項目,以下圖:
2,分別添加頭文件和cpp文件 算法
// 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
// 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' c#
extern _declspec(dllexport) int add(int x,int y); // 聲明爲C編譯、連接方式的外部函數 extern _declspec(dllexport) int sub(int x,int y); // 聲明爲C編譯、連接方式的外部函數暫時尚未發現其餘問題。
3,按F6編譯,在相應的Debug文件夾裏面能夠找到生成的.dll文件。 less
第二部分:C#調用方式dll 函數
1,創建一個工程,而後在SolutionExplorer窗口,選中須要動態連接庫(DLL)的工程(project),右擊添加已有文件,選擇上面生成的.dll文件,而後加入到工程中來。
2,在SolutionExplorer窗口,選中該文件,在下面Properties窗口中,更改其 ui
3,在C#程序中加入以下代碼,就可使用了。 spa
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
一、爲了便於改下已經存在的c或者cpp項目,能夠按照第一部分的作法先新建一個.dll工程。便於下面修改代碼。假設新建的.dll動態庫的工程爲NewDll,待改動的C或CPP工程爲OldC,下面以修改某個GSM_AMR算法爲.dll動態連接庫做例子,說明過程。 .net
二、用VS2010打開OldC,右擊OldC工程,添加已存在文件,找到NewDll文件夾裏面的dllmain.cpp文件,按F6,若是報錯,看缺乏那些頭文件。通常BOOL被報錯,說明缺乏stdax.h等,一直添加NewDll工程裏面的頭文件,直至可能提醒可能#include 「XXXX.h」不存在。通常這是因爲該頭文件和其餘頭文件不在同一個目錄下,能夠將他們調整到同一個目錄下面。 調試
三、右擊OldC工程的Properties屬性,打開,修改輸出類型爲DLL,而不是.exe文件。這個能夠本身慢慢找,總會找到的,通常打開的窗口就是能夠修改輸出類型的。 code
四、按F10找到OldC的主函數main(),通常main()所在的文件都沒有對應的頭文件。能夠爲他創建一個同名頭文件,按照第一部分裏面的說明,把main()函數裏面的頭文件都複製到該同名頭文件裏,而後添加第一部分的代碼CDLL.h裏面的以下代碼。
// 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修改爲你想要的函數格式。
五、在main()所在的文件裏面添加你所須要的函數體。
6,按F6,應該出現Build success,若是出現什麼問題,極有多是上面第一部分提的那個問題,能夠按照上面的方式解決。生成的.dll文件,能夠到相應的Debug裏面去找。
第四部分:手把手教你把C語言的MELP語音壓縮算法改成dll形式
一、首先網上搜索melp C,能夠下載到美國軍方標準的MELP開源的C代碼。具體網址就不提供了。
二、打開VS2010(個人是英文版的),New Project->選擇VisualC++的win32 project,餘下的部分就和第一部分有點重複了。本文的工程名字:FileMelp
三、因爲閱讀了該源代碼不少次了,瞭解了MELP算法的結構,以及幀的結構。編寫了幾個函數,方便調用。
四、回到第2步,右擊工程名字,添加已有文件,把MELP解壓縮後的文件都添加進來。
五、在melp.h文件最底部,加入以下的頭部,方便生成dll的函數頭部。
#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六、在melp.c的最底部,加入以下的函數體。
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文件中,放置到最後面一行。
七、調試dll代碼的過程,能夠參加我上面的博客。生成後代碼,就能夠用在你想要的C#裏面了。我在C#裏面調用的方式以下。其中生成的FileMelp.dll改爲了Melp.dll名字,如何添加到C#部分,詳細見上面的部分。這樣就能夠運行了。
#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