當前位置:首頁 » 編程軟體 » 空文件編譯庫

空文件編譯庫

發布時間: 2022-08-18 01:42:45

A. c++中如何把類編譯成類似於庫文件,以後直接包含頭文件即可

要寫一個dll,還要有一個lib文件,還要導出類等等,蠻復雜的,具體你可以網上查一查

B. 如何編譯一個 dll文件

創建DLL工程
這里,我們為了簡要說明DLL的原理,我們決定使用最簡單的編譯環境VC6.0,如下圖,我們先建立一個新的Win32 Dynamic-Link Library工程,名稱為「MyDLL」,在Visual Studio中,你也可以通過建立Win32控制台程序,然後在「應用程序類型」中選擇「DLL」選項,

點擊確定,選擇「一個空的DLL工程」,確定,完成即可。

一個簡單的dll
在第一步我們建立的工程中建立一個源碼文件」dllmain.cpp「,在「dllmain.cpp」中,鍵入如下代碼

[cpp] view plain
#include <Windows.h>
#include <stdio.h>

BOOL APIENTRY DllMain(HMODULE hMole, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH\n");
break;
}
return TRUE;
}
之後,我們直接編譯,即可以在Debug文件夾下,找到我們生成的dll文件,「MyDLL.dll」,注意,代碼裡面的printf語句,並不是必須的,只是我們用於測試程序時使用。而DllMain函數,是dll的進入/退出函數。

實際上,讓線程調用DLL的方式有兩種,分別是隱式鏈接和顯式鏈接,其目的均是將DLL的文件映像映射進線程的進程的地址空間。我們這里只大概提一下,不做深入研究,如果感興趣,可以去看《Window高級編程指南》的第12章內容。
隱式鏈接調用
隱士地鏈接是將DLL的文件影響映射到進程的地址空間中最常用的方法。當鏈接一個應用程序時,必須制定要鏈接的一組LIB文件。每個LIB文件中包含了DLL文件允許應用程序(或另一個DLL)調用的函數的列表。當鏈接器看到應用程序調用了某個DLL的LIB文件中給出的函數時,它就在生成的EXE文件映像中加入了信息,指出了包含函數的DLL文件的名稱。當操作系統載入EXE文件時,系統查看EXE文件映像的內容來看要裝入哪些DLL,而後試圖將需要的DLL文件映像映射到進程的地址空間中。當尋找DLL時,系統在系列位置查找文件映像。

1.包含EXE映像文件的目錄
2.進程的當前目錄
3.Windows系統的目錄
4.Windows目錄
5.列在PATH環境變數中的目錄

這種方法,一般都是在程序鏈接時控制,反映在鏈接器的配置上,網上大多數講的各種庫的配置,比如OPENGL或者OPENCV等,都是用的這種方法

顯式鏈接調用
這里我們只提到兩種函數,一種是載入函數
[cpp] view plain
HINSTANCE LoadLibrary(LPCTSTR lpszLibFile);

HINSTANCE LoadLibraryEx(LPCSTR lpszLibFile,HANDLE hFile,DWORD dwFlags);
返回值HINSTANCE值指出了文件映像映射的虛擬內存地址。如果DLL不能被映進程的地址空間,函數就返回NULL。你可以使用類似於

[cpp] view plain
LoadLibrary("MyDLL")
或者

[cpp] view plain
LoadLibrary("MyDLL.dll")
的方式進行調用,不帶後綴和帶後綴在搜索策略上有區別,這里不再詳解。

顯式釋放DLL

在顯式載入DLL後,在任意時刻可以調用FreeLibrary函數來顯式地從進程的地址空間中解除該文件的映像。
[cpp] view plain
BOOL FreeLibrary(HINSTANCE hinstDll);
這里,在同一個進程中調用同一個DLL時,實際上還牽涉到一個計數的問題。這里也不在詳解。
線程可以調用GetMoleHandle函數:

[cpp] view plain
GetMoleHandle(LPCTSTR lpszMoleName);
來判斷一個DLL是否被映射進進程的地址空間。例如,下面的代碼判斷MyDLL.dll是否已被映射到進程的地址空間,如果沒有,則裝入它:

[cpp] view plain
HINSTANCE hinstDll;
hinstDll = GetMoleHandle("MyDLL");
if (hinstDll == NULL){
hinstDll = LoadLibrary("MyDLL");
}
實際上,還有一些函數,比如 GetMoleFileName用來獲取DLL的全路徑名稱,FreeLibraryAndExitThread來減少DLL的使用計數並退出線程。具體內容還是參見《Window高級編程指南》的第12章內容,此文中不適合講太多的內容以至於讀者不能一下子接受。

DLL的進入與退出函數

說到這里,實際上只是講了幾個常用的函數,這一個小節才是重點。
在上面,我們看到的MyDLL的例子中,有一個DllMain函數,這就是所謂的進入/退出函數。系統在不同的時候調用此函數。這些調用主要提供信息,常常被DLL用來執行進程級或線程級的初始化和清理工作。如果你的DLL不需要這些通知,就不必再你的DLL源代碼中實現此函數,例如,如果你創建的DLL只含有資源,就不必實現該函數。但如果有,則必須像我們上面的格式。
DllMain函數中的ul_reason_for_call參數指出了為什麼調用該函數。該參數有4個可能值: DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH、DLL_PROCESS_DETACH。
其中,DLL_PROCESS_ATTACH是在一個DLL首次被映射到進程的地址空間時,系統調用它的DllMain函數,傳遞的ul_reason_for_call參數為DLL_PROCESS_ATTACH。這只有在首次映射時發生。如果一個線程後來為已經映射進來的DLL調用LoadLibrary或LoadLibraryEx,操作系統只會增加DLL的計數,它不會再用DLL_PROCESS_ATTACH調用DLL的DllMain函數。
而DLL_PROCESS_DETACH是在DLL被從進程的地址空間解除映射時,系統調用它的DllMain函數,傳遞的ul_reason_for_call值為DLL_PROCESS_DETACH。我們需要注意的是,當用DLL_PROCESS_ATTACH調用DLL的DllMain函數時,如果返回FALSE,說明初始化不成功,系統仍會用DLL_PROCESS_DETACH調用DLL的DllMain。因此,必須確保沒有清理那些沒有成功初始化的東西。
DLL_THREAD_ATTACH:當進程中創建一個線程時,系統察看當前映射到進程的地址空間中的所有DLL文件映像,並用值DLL_THREAD_ATTACH調用所有的這些DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的初始化。注意,當映射一個新的DLL時,進程中已有的幾個線程在運行,系統不會為已經運行的線程用值DLL_THREAD_ATTACH調用DLL的DllMain函數。
而DLL_THREAD_DETACH,如果線程調用ExitThread來終結(如果讓線程函數返回而不是調用ExitThread,系統會自動調用ExitThread),系統察看當前映射到進程空間的所有DLL文件映像,並用值DLL_THREAD_DETACH來調用所有的DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的清理工作。
這里,我們需要注意的是,如果線程的終結是因為系統中的一個線程調用了TerminateThread,系統就不會再使用DLL_THREAD_DETACH來調用DLL和DllMain函數。這與TerminateProcess一樣,不再萬不得已時,不要使用。
下面,我們貼出《Window高級編程指南》中的兩個圖來說明上述四種參數的調用情況。

好的,介紹了以上的情況,下面,我們來繼續實踐,這次,建立一個新的空的win32控制台工程TestDLL,不再多說,代碼如下:

[cpp] view plain
#include <iostream>
#include <Windows.h>
using namespace std;

DWORD WINAPI someFunction(LPVOID lpParam)
{
cout << "enter someFunction!" << endl;
Sleep(1000);
cout << "This is someFunction!" << endl;
Sleep(1000);
cout << "exit someFunction!" << endl;
return 0;
}

int main()
{
HINSTANCE hinstance = LoadLibrary("MyDLL");
if(hinstance!=NULL)
{
cout << "Load successfully!" << endl;
}else {
cout << "Load failed" << endl;
}
HANDLE hThread;
DWORD dwThreadId;

cout << "createThread before " << endl;
hThread = CreateThread(NULL,0,someFunction,NULL,0,&dwThreadId);
cout << "createThread after " << endl;
cout << endl;

Sleep(3000);

cout << "waitForSingleObject before " << endl;
WaitForSingleObject(hThread,INFINITE);
cout << "WaitForSingleObject after " << endl;
cout << endl;

FreeLibrary(hinstance);
return 0;
}

代碼很好理解,但是前提是,你必須對線程有一定的概念。另外,注意,我們上面編譯的獲得的「MyDLL.dll"必須拷貝到能夠讓我們這個工程找到的地方,也就是上面我們提到的搜索路徑中的一個地方。
這里,我們先貼結果,當然,這只是在我機器上其中某次運行結果。

有了上面我們介紹的知識,這個就不是很難理解,主進程在調用LoadLibrary時,用DLL_PROCESS_ATTACH調用了DllMain函數,而線程創建時,用DLL_THREAD_ATTACH調用了DllMain函數,而由於主線程和子線程並行的原因,可能輸出的時候會有打斷。但是,這樣反而能讓我們更清楚的理解程序。

C. linux下c編程怎麼編譯

有以下步驟:

1.源程序的編譯
在Linux下面,如果要編譯一個c語言源程序,我們要使用GNU的gcc編譯器. 下面
我們以一個實例來說明如何使用gcc編譯器.
假設我們有下面一個非常簡單的源程序(hello.c):
int main(int argc,char **argv)
{
printf("Hello Linux\n");
}
要編譯這個程序,我們只要在命令行下執行:
gcc -o hello hello.c
gcc 編譯器就會為我們生成一個hello的可執行文件.執行./hello就可以看到程
序的輸出結果了.命令行中 gcc表示我們是用gcc來編譯我們的源程序,-o 選項表示
我們要求編譯器給我們輸出的可執行文件名為hello 而hello.c是我們的源程序文件.
gcc編譯器有許多選項,一般來說我們只要知道其中的幾個就夠了. -o選項我們
已經知道了,表示我們要求輸出的可執行文件名. -c選項表示我們只要求編譯器輸出
目標代碼,而不必要輸出可執行文件. -g選項表示我們要求編譯器在編譯的時候提
供我們以後對程序進行調試的信息.
知道了這三個選項,我們就可以編譯我們自己所寫的簡單的源程序了,如果你
想要知道更多的選項,可以查看gcc的幫助文檔,那裡有著許多對其它選項的詳細說
明.
2.Makefile的編寫
假設我們有下面這樣的一個程序,源代碼如下:

#include "mytool1.h"
#include "mytool2.h"
int main(int argc,char **argv)
{
mytool1_print("hello");
mytool2_print("hello");
}

#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif

#include "mytool1.h"
void mytool1_print(char *print_str)
{
printf("This is mytool1 print %s\n",print_str);
}

#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif

#include "mytool2.h"
void mytool2_print(char *print_str)
{
printf("This is mytool2 print %s\n",print_str);
}
當然由於這個程序是很短的我們可以這樣來編譯
gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o
這樣的話我們也可以產生main程序,而且也不時很麻煩.但是如果我們考慮一
下如果有一天我們修改了其中的一個文件(比如說mytool1.c)那麼我們難道還要重
新輸入上面的命令?也許你會說,這個很容易解決啊,我寫一個SHELL腳本,讓她幫我
去完成不就可以了.是的對於這個程序來說,是可以起到作用的.但是當我們把事情
想的更復雜一點,如果我們的程序有幾百個源程序的時候,難道也要編譯器重新一
個一個的去編譯?
為此,聰明的程序員們想出了一個很好的工具來做這件事情,這就是make.我們
只要執行以下make,就可以把上面的問題解決掉.在我們執行make之前,我們要先
編寫一個非常重要的文件.--Makefile.對於上面的那個程序來說,可能的一個
Makefile的文件是:
# 這是上面那個程序的Makefile文件
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
有了這個Makefile文件,不過我們什麼時候修改了源程序當中的什麼文件,我們
只要執行make命令,我們的編譯器都只會去編譯和我們修改的文件有關的文件,其
它的文件她連理都不想去理的.
下面我們學習Makefile是如何編寫的.
在Makefile中也#開始的行都是注釋行.Makefile中最重要的是描述文件的依賴
關系的說明.一般的格式是:
target: components
TAB rule
第一行表示的是依賴關系.第二行是規則.
比如說我們上面的那個Makefile文件的第二行
main:main.o mytool1.o mytool2.o
表示我們的目標(target)main的依賴對象(components)是main.o mytool1.o
mytool2.o 當倚賴的對象在目標修改後修改的話,就要去執行規則一行所指定的命
令.就象我們的上面那個Makefile第三行所說的一樣要執行 gcc -o main main.o
mytool1.o mytool2.o 注意規則一行中的TAB表示那裡是一個TAB鍵
Makefile有三個非常有用的變數.分別是$@,$^,$<代表的意義分別是:
$@--目標文件,$^--所有的依賴文件,$<--第一個依賴文件.
如果我們使用上面三個變數,那麼我們可以簡化我們的Makefile文件為:
# 這是簡化後的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
經過簡化後我們的Makefile是簡單了一點,不過人們有時候還想簡單一點.這里
我們學習一個Makefile的預設規則
.c.o:
gcc -c $<
這個規則表示所有的 .o文件都是依賴與相應的.c文件的.例如mytool.o依賴於
mytool.c這樣Makefile還可以變為:
# 這是再一次簡化後的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
.c.o:
gcc -c $<
好了,我們的Makefile 也差不多了,如果想知道更多的關於Makefile規則可以查
看相應的文檔.

3.程序庫的鏈接
試著編譯下面這個程序

#include
int main(int argc,char **argv)
{
double value;
printf("Value:%f\n",value);
}
這個程序相當簡單,但是當我們用 gcc -o temp temp.c 編譯時會出現下面所示
的錯誤.
/tmp/cc33Ky.o: In function `main':
/tmp/cc33Ky.o(.text+0xe): undefined reference to `log'
collect2: ld returned 1 exit status
出現這個錯誤是因為編譯器找不到log的具體實現.雖然我們包括了正確的頭
文件,但是我們在編譯的時候還是要連接確定的庫.在Linux下,為了使用數學函數,我
們必須和數學庫連接,為此我們要加入 -lm 選項. gcc -o temp temp.c -lm這樣才能夠
正確的編譯.也許有人要問,前面我們用printf函數的時候怎麼沒有連接庫呢?是這樣
的,對於一些常用的函數的實現,gcc編譯器會自動去連接一些常用庫,這樣我們就沒
有必要自己去指定了. 有時候我們在編譯程序的時候還要指定庫的路徑,這個時候
我們要用到編譯器的 -L選項指定路徑.比如說我們有一個庫在 /home/hoyt/mylib下
,這樣我們編譯的時候還要加上 -L/home/hoyt/mylib.對於一些標准庫來說,我們沒
有必要指出路徑.只要它們在起預設庫的路徑下就可以了.系統的預設庫的路徑/lib
/usr/lib /usr/local/lib 在這三個路徑下面的庫,我們可以不指定路徑.
還有一個問題,有時候我們使用了某個函數,但是我們不知道庫的名字,這個時
候怎麼辦呢?很抱歉,對於這個問題我也不知道答案,我只有一個傻辦法.首先,我到
標准庫路徑下面去找看看有沒有和我用的函數相關的庫,我就這樣找到了線程
(thread)函數的庫文件(libpthread.a). 當然,如果找不到,只有一個笨方法.比如我要找
sin這個函數所在的庫. 就只好用 nm -o /lib/*.so|grep sin>~/sin 命令,然後看~/sin
文件,到那裡面去找了. 在sin文件當中,我會找到這樣的一行libm-2.1.2.so:00009fa0
W sin 這樣我就知道了sin在 libm-2.1.2.so庫裡面,我用 -lm選項就可以了(去掉前面
的lib和後面的版本標志,就剩下m了所以是 -lm).

4.程序的調試
我們編寫的程序不太可能一次性就會成功的,在我們的程序當中,會出現許許
多多我們想不到的錯誤,這個時候我們就要對我們的程序進行調試了.
最常用的調試軟體是gdb.如果你想在圖形界面下調試程序,那麼你現在可以選
擇xxgdb.記得要在編譯的時候加入 -g選項.關於gdb的使用可以看gdb的幫助文件.由
於我沒有用過這個軟體,所以我也不能夠說出如何使用. 不過我不喜歡用gdb.跟蹤
一個程序是很煩的事情,我一般用在程序當中輸出中間變數的值來調試程序的.當
然你可以選擇自己的辦法,沒有必要去學別人的.現在有了許多IDE環境,裡面已經自
己帶了調試器了.你可以選擇幾個試一試找出自己喜歡的一個用.

5.頭文件和系統求助
有時候我們只知道一個函數的大概形式,不記得確切的表達式,或者是不記得函數在那個頭文件進行了說明.這個時候我們可以求助系統,比如說我們想知道fread這個函數的確切形式,我們只要執行 man fread 系統就會輸出著函數的詳細解釋的.和這個函數所在的頭文件說明了。如果我們要write這個函數說明,當我們執行man write時,輸出的結果卻不是我們所需要的。因為我們要的是write這個函數的說明,可是出來的卻是write這個命令的說明。為了得到write的函數說明我們要用man 2 write。2表示我們用的是write這個函數是系統調用函數,還有一個我們常用的是3表示函數是c的庫函數。

D. 新增了一個空文件夾在WebContent下,服務啟動後,查看編譯後的文件,該文件夾沒有出現在wtpwebapps

因為你在編譯的時候沒有把這個文件一起編譯進去,所以沒有!只需要在設置編譯時把這個文件夾也編譯進去就行!!望採納!!謝謝!!

E. CMake+MinGW編譯OpenCV2.1以後為什麼Bin和Lib文件夾是空的

你要使用opencv寫程序,有兩個步驟
1,先編譯出opencv的庫
2,再寫一個程序,鏈接第一步產生的opencv庫。

你顯然第一步都沒有完成。
cmake只是產生一個項目文件,如果你使用codeblocks的話,那麼還需要在codeblocks裡面把opencv的庫給編譯出來。

F. vc6.0編輯器怎麼建立個能編寫c語言的空白文件

文件-新建-
選擇
新建文件
裡面的
C++sourceFile文件,
然後再
文件名
裡面輸入
****.c
注意一定寫成***.c

要不默認會成為cpp文件的,
然後再裡面寫
代碼
,編譯運行就可以了

G. linux 除了.o so a 還有哪些二進制文件

Linux下文件的類型是不依賴於其後綴名的,但一般來講:
.o,是目標文件,相當於windows中的.obj文件
.so 為共享庫,是shared object,用於動態連接的,和dll差不多
.a為靜態庫,是好多個.o合在一起,用於靜態連接
.la為libtool自動生成的一些共享庫,vi編輯查看,主要記錄了一些配置信息。可以用如下命令查看
*.la文件的格式 $file *.la
*.la: ASCII English text
所以可以用vi來查看其內容。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
創建.a庫文件和.o庫文件:
[yufei@localhost perl_c2]$ pwd
/home/yufei/perl_c2
[yufei@localhost perl_c2]$ cat mylib.c
#include <stdio.h>
#include <string.h>
void hello(){
printf("success call from perl to c library\n");
}
[yufei@localhost perl_c2]$ cat mylib.h
extern void hello();

[yufei@localhost perl_c2]$ gcc -c mylib.c
[yufei@localhost perl_c2]$ dir
mylib.c mylib.h mylib.o
[yufei@localhost perl_c2]$ ar -r mylib.a mylib.o
ar: 正在創建 mylib.a
[yufei@localhost perl_c2]$ dir
mylib.a mylib.c mylib.h mylib.o

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

1111111111111111111111
1111111
動態鏈接庫*.so的編譯與使用- -

動態庫*.so在Linux下用c和c++編程時經常會碰到,最近在網站找了幾篇文章介紹動態庫的編譯和鏈
接,總算搞懂了這個之前一直不太了解得東東,這里做個筆記,也為其它正為動態庫鏈接庫而苦惱的兄弟
們提供一點幫助。
1、動態庫的編譯
下面通過一個例子來介紹如何生成一個動態庫。這里有一個頭文件:so_test.h,三個.c文件:
test_a.c、test_b.c、test_c.c,我們將這幾個文件編譯成一個動態庫:libtest.so。
so_test.h:
#include <stdio.h>
#include <stdlib.h>
void test_a();
void test_b();
void test_c();
test_a.c:
#include "so_test.h"
void test_a()
{
printf("this is in test_a...\n");
}
test_b.c:
#include "so_test.h"
void test_b()
{
printf("this is in test_b...\n");
}
test_c.c:
#include "so_test.h"
void test_c()
{
printf("this is in test_c...\n");
}
將這幾個文件編譯成一個動態庫:libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
2、動態庫的鏈接
在1、中,我們已經成功生成了一個自己的動態鏈接庫libtest.so,下面我們通過一個程序來調用這
個庫里的函數。程序的源文件為:test.c。
test.c:
#include "so_test.h"
int main()
{
test_a();
test_b();
test_c();
return 0;
}
l 將test.c與動態庫libtest.so鏈接生成執行文件test:
$ gcc test.c -L. -ltest -o test
l 測試是否動態連接,如果列出libtest.so,那麼應該是連接正常了
$ ldd test
l 執行test,可以看到它是如何調用動態庫中的函數的。
3、編譯參數解析
最主要的是GCC命令行的一個選項:
-shared 該選項指定生成動態連接庫(讓連接器生成T類型的導出符號表,有時候也生成
弱連接W類型的導出符號),不用該標志外部程序無法連接。相當於一個可執行文件
l -fPIC:表示編譯為位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動
態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。
l -L.:表示要連接的庫在當前目錄中
l -ltest:編譯器查找動態連接庫時有隱含的命名規則,即在給出的名字前面加上lib,後
面加上.so來確定庫的名稱
l LD_LIBRARY_PATH:這個環境變數指示動態連接器可以裝載動態庫的路徑。
l 當然如果有root許可權的話,可以修改/etc/ld.so.conf文件,然後調用 /sbin/ldconfig來
達到同樣的目的,不過如果沒有root許可權,那麼只能採用輸出LD_LIBRARY_PATH的方法了。
4、注意
調用動態庫的時候有幾個問題會經常碰到,有時,明明已經將庫的頭文件所在目錄 通過 「-I
」 include進來了,庫所在文件通過「-L」參數引導,並指定了「-l」的庫名,但通過ldd命令察看時,
就是死活找不到你指定鏈接的so文件,這時你 要作的就是通過修改LD_LIBRARY_PATH或
者/etc/ld.so.conf文件來指定動態庫的目錄。通常這樣做就可以解決庫無法鏈接的問題 了。
makefile裡面怎麼正確的編譯和連接生成.so庫文件,然後又是在其他程序的makefile裡面如何編譯
和連接才能調用這個庫文件的函數????
答:
你需要告訴動態鏈接器、載入器ld.so在哪裡才能找到這個共享庫,可以設置環境變數把庫的
路徑添加到庫目錄/lib和/usr/lib,LD_LIBRARY_PATH=$(pwd),這種方法採用命令行方法不太方便,一種替
代方法
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注釋^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LD_LIBRARY_PATH可以在/etc/profile還是 ~/.profile還是 ./bash_profile里設置,或者.bashrc里

改完後運行source /etc/profile或 . /etc/profile
更好的辦法是添入/etc/ld.so.conf, 然後執行 /sbin/ldconfig
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^注釋^^^^^^^^^^^^^^^^^^^^^^^^^^^^
是把庫路徑添加到/etc/ld.so.conf,然後以root身份運行ldconfig
也可以在連接的時候指定文件路徑和名稱 -I -L.
GCC=gcc
CFLAGS=-Wall -ggdb -fPIC
#CFLAGS=
all: libfunc test
libfunc:func.o func1.o
$(GCC) -shared -Wl,-soname,libfunc.so.1 -o libfunc.so.1.1 $<
ln -sf libfunc.so.1.1 libfunc.so.1
ln -sf libfunc.so.1 libfunc.so
***********************************************注釋
************************************************
ln -s是用來創建軟鏈接,也就相當於windows中的快捷方式,在當前目錄中創建上一級目錄中的文件
ttt的命名為ttt2軟鏈接的命令是ln -s ../ttt ttt2,如果原文件也就是ttt文件刪除的話,ttt2也變成了
空文件。
ln -d是用來創建硬鏈接,也就相當於windows中文件的副本,當原文件刪除的時候,並不影響「副本
」的內容。
編譯目標文件時使用gcc的-fPIC選項,產生與位置無關的代碼並能被載入到任何地址:
gcc –fPIC –g –c liberr.c –o liberr.o
使用gcc的-shared和-soname選項;
使用gcc的-Wl選項把參數傳遞給連接器ld;
使用gcc的-l選項顯示的連接C庫,以保證可以得到所需的啟動(startup)代碼,從而避免程序在使
用不同的,可能不兼容版本的C庫的系統上不能啟動執行。
gcc –g –shared –Wl,-soname,liberr.so –o liberr.so.1.0.0 liberr.o –lc
建立相應的符號連接:
ln –s liberr.so.1.0.0 liberr.so.1;
ln –s liberr.so.1.0.0 liberr.so;
在MAKEFILE中:
$@
表示規則中的目標文件集。在模式規則中,如果有多個目標,那麼,"$@"就是匹配於目標中模式
定義的集合。
$%
僅當目標是函數庫文件中,表示規則中的目標成員名。例如,如果一個目標是"foo.a(bar.o)",
那麼,"$%"就是"bar.o","$@"就是"foo.a"。如果目標不是函數庫文件(Unix下是[.a],Windows下是
[.lib]),那麼,其值為空。
$<
依賴目標中的第一個目標名字。如果依賴目標是以模式(即"%")定義的,那麼"$<"將是符合模
式的一系列的文件集。注意,其是一個一個取出來的。
$?
所有比目標新的依賴目標的集合。以空格分隔。
$^
所有的依賴目標的集合。以空格分隔。如果在依賴目標中有多個重復的,那個這個變數會去除重
復的依賴目標,只保留一份。
*********************************************注釋
***********************************************************************
test: test.o libfunc
$(GCC) -o test test.o -L. -lfunc
%.o:%.c
$(GCC) -c $(CFLAGS) -o $@ $<
clean:
rm -fr *.o
rm -fr *.so*
rm -fr test
要生成.so文件,cc要帶-shared 參數;要調用.so的文件,比如libfunc.so,可以在cc命令最後加上
-lfunc,還要視情況加上-L/usr/xxx 指出libfunc.so的路徑;這樣,在你要編譯的源文件中就可以調用
libfunc.so這個庫文件的函數.
前面的都說的差不多了,最後提醒一下最好提供一個介面頭文件
動態載入,用dlopen,dlclose,dlsym

H. C#中如何使用頭文件(xxxx.h),以及如何將頭文件編譯成動態鏈接庫(DLL)

頭文件、cpp文件和dll文件之間的是這樣的關系:頭文件聲明方法,cpp實現方法、cpp編譯後得到dll,因此頭文件描述的是dll文件的介面,也就是具體實現的介面。如果你只有dll文件,只要知道其導出的方法就可以直接使用,win32有對應的api。如果想要將dll中的所有可用方法包含到項目中,就要包含頭文件。這就是說,頭文件和dll文件是對應的。另外,如果你的頭文件中已經包含了實現代碼,那你需要提供一個空的cpp文件,包含該頭文件,並將它們編譯成dll文件。
C#沒法直接用C++的頭文件,但是可以直接用dll,使用的技術稱作PInvoke,原理是在C#代碼中用extern關鍵字添加dll中所需方法的簽名,也就是二樓說的那種方法。此外,如果這個dll是採用com技術實現的,也可以使用.NET平台提供的COM互操作特性直接導入使用。

I. 在TC中,怎樣用命令編譯lib庫

定義函數庫的方法及應用:
一、2個相關的命令
1、TCC——TC的DOS下的命令行編譯連接工具
2、TLIB——TC的DOS下的庫操作工具
二、1個自定義的函數庫的例子
1、
在TC集成環境下,編一個文件USERADD.C
#define
_NO_MAIN
int
add(int
*a,int
*b)
{
int
c;
c=(*a)+(*b);
return
c;
}
按ALT—F9編譯
生成一個
USERADD.OBJ文件。
2、按F10—F—O
退到DOSSHELL(DOS環境下)
COPY
USERADD.OBJ

..\LIB目錄,在\LIB目錄下執行
TLIB
USERLIB.LIB+USERADD.OBJ
就生成了一個自己的函數庫
USERLIB,在這個函數庫里就包含了函數模塊
int
add(int
*a,int
*b)
的二進制代碼。現在已經將自定義的函數放進了函數庫,就可以把原文件USERADD.C刪掉不要了。(當然,為了以後維護方便,還是作一個備份為好)。
以後如有其它的函數模塊,也可以編譯後用TLIB
命令加入到這個函數庫里。
3、寫一個包含文件
USER1.H,寫完後COPY到INCLUDE
目錄。內容如下:
int
add(int
*,int
*);
4、作好了以上的自定義函數庫的准備工作,現在就可以使用了。
寫一個程序,取名為ADD-1.C,在程序中調用庫函數add(
);
#include
#include
void
main(
)
{
int
a,b,c;
a=20;b=30;
c=add(&a,&b);
printf(「%d」,c);
}
5、在DOS命令行下,執行
TCC
ADD-1.C
..\LIB\USERLIB.LIB
就OK!
運行ADD-1.EXE,可以看到輸出結果
50
Tc生成lib的方法:
擴展庫與自建LIB庫使用擴展庫TC所帶的庫在有的情況下是無法滿足功能要求的,自己寫一個太麻煩,找到了一個LIB庫又怕不會用。在WIN-TC中,對於使用外部的擴展庫(第三方LIB)提供了一個方便的解決方法:首先要確定你的LIB庫是FOR
TC版本的而不是FOR
VC或是其它的。如果確定是FOR
TC的版本的話就把你的首標文件(或稱頭文件),就是擴展名為*.h的文件拷貝到WIN-TC的include目錄里,然後把相應名稱的*.lib文件拷貝到lib目錄,然後再運行WIN-TC時選擇「編譯配置」菜單項,你會看到擴展庫信息欄目里有你的LIB庫文件名在上面了,但是沒有打鉤。然後你把它鉤選後再「確定」保存,以後的編譯程序時就自動鏈接該擴展庫了。自建立LIB庫將自己的代碼編譯成LIB庫的格式有利與保護自己的代碼版權。如何來生成自己的LIB庫呢?請按照下面的方法:
STEP
1——生成目標代碼(OBJ)
建立mylib的代碼文件/*********************
mylib.c
*********************/void
myfun(){printf("
myfun()
in
mylib.lib
");}然後保存為WIN-TC目錄下的mylib.c文件然後到菜單項:運行->編譯設置
看看「產生
OBJ
文件」是否已選擇,若未選擇則選擇之。然後回到主界面,點「編譯鏈接」按鈕(F9

熱點內容
精易編程 發布:2025-02-07 00:49:10 瀏覽:464
訪問桂綸鎂 發布:2025-02-07 00:49:00 瀏覽:937
安卓免費掃描哪個好 發布:2025-02-07 00:47:40 瀏覽:90
金蝶修改伺服器地址 發布:2025-02-07 00:41:08 瀏覽:867
安卓手機版的蒸汽平台在哪裡下載 發布:2025-02-07 00:29:04 瀏覽:454
php自學中心 發布:2025-02-07 00:28:50 瀏覽:270
手機卡在哪裡設置密碼 發布:2025-02-07 00:21:25 瀏覽:707
解壓哄睡音頻 發布:2025-02-07 00:19:56 瀏覽:159
資料庫系統第六版答案 發布:2025-02-07 00:06:10 瀏覽:971
fut加密毛發怎麼樣 發布:2025-02-07 00:06:01 瀏覽:868