2012-05-02 59 views
5

Theo tiêu đề, tôi đang cố gắng xây dựng một DLL bằng cách sử dụng C và liên kết nó từ một dự án C++. Tôi đọc và làm theo các hướng dẫn khác nhau trên internet nhưng mọi thứ đều thiếu một cái gì đó và tôi không hiểu điều gì.Tạo một DLL trong C và liên kết nó từ một dự án C++

Đây là những gì tôi đã làm, từng bước:

Tôi tạo ra một dự án Win32 mới, được đặt tên testlib, sau đó, từ trình hướng dẫn, tôi đã chọn "DLL" và "dự án rỗng".

Added một tiêu đề:

//testlib.h 

#include <stdio.h> 

__declspec(dllexport) void hello(); 

Added một nguồn; vì tôi muốn nó là nguồn C tôi đọc nên đơn giản đổi tên tệp .cpp trong .c, do đó,

//testlib.c 

#include "testlib.h" 

void hello() { 
    printf("DLL hello() called\n"); 
} 

Xây dựng thành công.

Bây giờ tôi muốn sử dụng dll hữu ích của mình trong một dự án khác.

Sau đó: dự án mới (testlibUse). Lần này tôi chọn "Empty project".
Không cần phải thêm một tiêu đề, vừa tạo ra một nguồn cpp

//main.cpp 
#include <testlib.h> 

int main() { 
    hello(); 
} 

Sau đó:

  • tôi đã thêm đường dẫn đến thư mục mà là testlib.dll trong Properties-> VC++ directories-> thư mục Executable

  • Tôi đã thêm đường dẫn vào thư mục ở đó là testlib.h trong Thuộc tính-> VC++ folders-> Bao gồm thư mục

  • tôi đã thêm đường dẫn đến testlib.lib (bao gồm phần mở rộng) trong Properties-> Linker-> Input-> phụ thuộc bổ sung

Tôi cố gắng để xây dựng nhưng tôi có một mối liên kết lỗi:

LINK : C:\path\testlibUse\Debug\testlibUse.exe not found or not built by the last incremental link; performing full link
main.obj : error LNK2019: unresolved external symbol "void __cdecl hello(void)" ([email protected]@YAXXZ) referenced in function _main
C:\path\testlibUse\Debug\testlibUse.exe : fatal error LNK1120: 1 unresolved externals

Nếu tôi quay lại testlib, đổi tên lại testlib.c trong testlib.cpp và xây dựng lại dll, sau đó tôi có thể xây dựng testlibUse nhưng tôi nhận được lỗi "không tìm thấy dll" khi chạy.

Tôi cũng đã thử thay đổi cấu hình của cả hai dự án trong "Bản phát hành" (thay đổi đường dẫn khi cần) nhưng không có gì thay đổi.

Xin lỗi vì bài đăng dài nhưng tôi nghĩ cần ghi lại chính xác những gì tôi đã làm.

Mọi đề xuất?

Ngoài ra, có bất kỳ thông số cấu hình nào tôi cần thay đổi không nếu tôi muốn sử dụng dll của mình trong dự án Qt?

Trả lời

9

Bạn có một vài vấn đề:

  1. File header nên đánh dấu các chức năng như xuất khẩu khi được biên soạn trong DLL nhưng nhập khẩu khi được biên soạn bởi người dùng thư viện.
  2. Tệp tiêu đề phải bao bọc các khai báo hàm trong khối extern "C" khi được biên dịch dưới dạng C++ để đảm bảo rằng các tên không bị cắt xén
  3. DLL không nằm trên đường dẫn tìm kiếm trong thư viện thực thi của bạn. trong thời gian chạy.

Để khắc phục (1) và (2), viết lại tiêu đề của bạn như thế này:

#ifdef __cplusplus 
extern "C" { 
#endif 

// Assume this symbol is only defined by your DLL project, so we can either 
// export or import the symbols as appropriate 
#if COMPILING_MY_TEST_DLL 
#define TESTLIB_EXPORT __declspec(dllexport) 
#else 
#define TESTLIB_EXPORT __declspec(dllimport) 
#endif 

TESTLIB_EXPORT void hello(); 
// ... more function declarations, marked with TESTLIB_EXPORT 

#ifdef __cplusplus 
} 
#endif 

Để khắc phục (3), sao chép DLL vào thư mục tương tự như tập tin thực thi của bạn. Cài đặt "thư mục thực thi" bạn đang thiết lập không ảnh hưởng đến việc tìm kiếm DLL - xem MSDN để biết mô tả chi tiết về cách tìm kiếm DLL. Giải pháp tốt nhất cho bạn là sao chép tệp DLL của bạn vào thư mục nơi tệp thực thi của bạn hoạt động. Bạn có thể làm điều này bằng tay, hoặc thêm một bước sau xây dựng cho dự án của bạn mà thực hiện điều này cho bạn.

1

Dường như bạn cần đảm bảo trình biên dịch không phải là mangle tên biểu tượng trong bản dựng cpp. Bạn sẽ có thể thêm extern "C" vào định nghĩa trong testlib.h:

#ifdef __cplusplus 
extern "C" 
#endif 
__declspec(dllexport) void hello(); 
+0

Xây dựng thành công nhưng tôi gặp lỗi "không tìm thấy dll" khi chạy ... Không đủ để thêm đường dẫn vào dll trong Properties-> VC++ folders-> Executable directories? – Saphrosit

+0

@Saphrosit: Không, theo hiểu biết tốt nhất của tôi, điều đó sẽ không ảnh hưởng đến hoạt động của ứng dụng. Đọc mô tả trên trang thuộc tính đó; nó ảnh hưởng đến việc tìm kiếm các tệp nhị phân khi xây dựng dự án. Bạn cần tìm thấy DLL (ví dụ: thông qua biến môi trường PATH) khi chạy. –

2

Bạn nên extern "C" bao gồm:

+0

Xây dựng thành công nhưng tôi gặp lỗi "dll not found" khi chạy ... Không đủ để thêm đường dẫn vào dll trong Properties-> VC++ folders-> Executable directories? – Saphrosit

1

Đây là phương pháp cho tệp tiêu đề C của bạn có thể được bao gồm bởi C++. Đảm bảo đặt chỉ TESTLIB_EXPORTS trong các cài đặt tiền xử lý DLL preprocessor của bạn. Trong các dự án bao gồm tiêu đề này để sử dụng DLL, tiêu đề sẽ khai báo các hàm như là nhập khẩu thay vì xuất khẩu.

Trình bảo vệ __cplusplus sẽ yêu cầu trình biên dịch nhập các chức năng của bạn bằng cách sử dụng trang trí tên C thay vì trang trí tên C++.

#include <stdio.h> 

#ifdef TESTLIB_EXPORTS 
#define TESTLIB_API __declspec(dllexport) 
#else 
#define TESTLIB_API __declspec(dllimport) 
#endif 

#ifdef __cplusplus 
extern "C" { 
#endif 

TESTLIB_API void hello(); 
/* other prototypes here */ 

#ifdef __cplusplus 
} 
#endif 
Các vấn đề liên quan