2009-02-21 63 views
7

Tôi đã xây dựng một dll C++ mà tôi muốn gọi từ mã C#. Tôi có thể gọi một chức năng, nhưng khác ném một ngoại lệ khi mã C# cố gắng để tải các dll.Chức năng xuất từ ​​C++ dll sang C# P/Invoke

Phần header trông như thế này: (? Gì foo = foo có nghĩa là trong lĩnh vực tên)

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

này tạo ra một dll với bảng xuất khẩu hơi khó hiểu:

File Type: DLL 

Section contains the following exports for PPPManager.dll 

00000000 characteristics 
499F44F0 time date stamp Fri Feb 20 16:04:00 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000078E4 Install = Install 
     2 1 000079DC PPPConnect = PPPConnect 

P My/Khai báo các tuyên bố như sau:

[DllImport("PPPManager.dll")] 
private static extern bool Install(); 

[DllImport("PPPManager.dll")] 
private static extern bool PPPConnect(); 

Cuộc gọi cài đặt trả về không ngoại lệ, nhưng khi tôi gọi PPPConnec t, tôi nhận được một MissingMethodException - "Không thể tìm thấy một Entry Point 'PPPConnect' trong một PInvoke DLL 'PPPManager.dll'."

Tôi đã thử xóa chỉ thị extern và declspec khỏi khai báo hàm Install, do đó PPPConnect là hàm duy nhất được xuất và điều này vẫn không cho phép tôi gọi PPPConnect.

Tôi cũng đã thử thực hiện DllImport theo thứ tự; điều này cho kết quả tương tự như gọi bằng tên - Cài đặt trả về, nhưng PPPConnect ném ngoại lệ "Không thể tìm thấy một Entry Point '# 2' ...".

Nhật ký interop cho:

[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::Install(); 
BOOLEAN (I1_WINBOOL_VAL) Install(); 

JIT ERROR FOR PINVOKE METHOD (Managed -> Native): 
[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::PPPConnect(); 
BOOLEAN (I1_WINBOOL_VAL) PPPConnect(); 

Đây là cũng ngoài khu vực chuyên môn của tôi, vì vậy bất cứ đề nghị hoặc những suy nghĩ sẽ được hoan nghênh.

Cảm ơn, Paul

chỉnh sửa: Nó chỉ ra rằng mã này làm việc; vấn đề là với dll mới nhất không được tuyên truyền cho thiết bị. D'oh!

+0

Tôi chưa bao giờ nghe nói về log interop này - làm thế nào để cho phép/xem đó? – Charlie

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx Tôi chỉ mới bắt đầu sử dụng nó để thử và gỡ lỗi vấn đề này, nhưng có vẻ như nó đã giúp tôi tiết kiệm rất nhiều thời gian gỡ lỗi MissingMethodExceptions. – Symmetric

Trả lời

8

Bạn đang sử dụng tệp .def trong dự án dll của mình để xuất các chức năng đó? Nếu có, hãy xóa nó và thử lại. Đây chỉ là một đoán bởi vì nó trông giống như xuất khẩu của bạn không phải là những gì họ nên khi bạn làm một extern "C" declspec (dllexports).

Tôi cố gắng này ra với một C++ dll đơn giản sử dụng

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

và đơn giản C# ứng dụng sử dụng tờ khai PInvoke bạn và nó làm việc tốt.

Khi tôi đã làm một dumpbin/xuất khẩu trên dll tôi thấy:

Dump file PPPManager.dll

File Type: DLL

mục chứa kim ngạch xuất khẩu sau cho PPPManager.dll

00000000 characteristics 
499F6C2D time date stamp Fri Feb 20 20:51:25 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000110CD Install = @ILT+200(_Install) 
     2 1 00011069 PPPConnect = @ILT+100(_PPPConnect) 

Lưu ý rằng tên đã xuất khác nhau trong trường hợp của tôi.

+0

Cuối cùng nó chỉ ra rằng tôi đã không sao chép các dll mới nhất hơn, do sự hiểu lầm của tôi những gì 'Thêm tập tin để dự án' lệnh trong VS nào. Ý tưởng của bạn để thử một dll bị tước bỏ là hạt giống tôi cần phải đi và tìm ra điều đó. Cảm ơn! – Symmetric

+0

Tuyệt vời! Mừng vì tôi có thể giúp. –

0

Thông tin tuyệt vời, nhưng như bạn đã đề cập, mọi thứ đều theo thứ tự tại đây. Thử cài đặt Công cụ gỡ lỗi cho Windows và chạy:

kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*" 

để có được kết xuất tốt hơn của bảng biểu tượng; đó cũng là một cảnh mù, nhưng bạn cũng có thể thử:

extern "C" 
{ 
    __declspec(dllexport) BOOL Install(); 
    __declspec(dllexport) BOOL PPPConnect(); 
}; 

trong trường hợp __declspec đang làm điều gì đó kỳ lạ.

1

Có thể đơn giản là PPPConnect không theo cách bị hệ điều hành hiểu sai. Hãy thử triển khai cả hai InstallPPPConnect làm không có ops (chỉ cần yêu cầu họ trả lại TRUE mà không làm bất kỳ điều gì khác) và xem lỗi có còn hay không. Nếu vậy, hãy thử đổi thứ tự mà chúng được xuất (vẫn là không có op) và xem liệu vấn đề có liên quan đến việc đặt hàng (không) hoặc với thứ gì khác không.

Bạn cũng có thể sử dụng công cụ đồ họa depends để xác nhận bảng xuất của DLL trông như thế nào, nhưng tôi nghi ngờ vấn đề là đến từ các khu đó.

+0

Đây là những ý tưởng tốt cho việc cô lập vấn đề thực sự. Bạn cũng có thể thử thêm hàm thứ ba và xem điều gì sẽ xảy ra với hàm đó. – Charlie

1

Theo mô tả của bạn Cài đặt và PPPConnect chỉ khác nhau trong tên. Tôi đoán bạn chỉ cần sử dụng phiên bản .dll cũ với ứng dụng C# của bạn. Một cái không có PPPConnect được định nghĩa.

Các khai báo có vẻ đúng (theo như tôi có thể đánh giá mà không có nguồn).

0

sử dụng Dependency Walker và mở DLL của bạn để xác minh những gì phương pháp có sẵn