2012-04-11 12 views
15

Tôi đang cố gắng tìm hiểu P/Invoke, vì vậy tôi đã tạo ra một dll đơn giản trong C++Không thể tìm thấy một điểm vào khi gọi C++ dll trong C#

KingFucs.h:

namespace KingFuncs 
{ 
    class KingFuncs 
    { 
    public: 
     static __declspec(dllexport) int GiveMeNumber(int i); 
    }; 
} 

KingFuns.cpp :

#include "KingFuncs.h" 
#include <stdexcept> 

using namespace std; 

namespace KingFuncs 
{ 
    int KingFuncs::GiveMeNumber(int i) 
    { 
     return i; 
    } 
} 

Vì vậy, nó không biên dịch, sau đó chúng tôi đã copy dll này vào thư mục debug WPF của tôi, với mã:

[DllImport("KingFuncDll.dll", EntryPoint = "GiveMeNumber", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
     public static extern int GiveMeNumber(
       int i 
      ); 

Và gọi đó là nút bấm:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    int num = GiveMeNumber(123); 
} 

Nhưng nó mang lại cho tôi ngoại lệ:

Không thể tìm thấy một điểm vào tên 'GiveMeNumber' trong DLL 'KingFuncDll.dll'.

Thực sự .... tôi đã làm gì sai ... Rõ ràng là có thể tìm thấy tệp DLL, nếu không sẽ là một ngoại lệ khác. Nhưng tên phương pháp của tôi là chính xác như nhau .... Tôi không thể nghĩ ra lý do khác.

+1

Vui lòng xem câu hỏi của tôi tại đây: http://stackoverflow.com/questions/9849541/writing-c-intended-to-be-called-from-c –

+0

Tôi đã giải quyết cùng một câu hỏi và mô tả nó tại [bài đăng này] (https://stackoverflow.com/a/45263176/1817569). – Hamid

Trả lời

31

Bạn cần sử dụng extern "C" khi bạn xuất hàm của mình để bạn chặn tên C++ mangling. Và bạn cũng không nên cố gắng p/gọi cho các thành viên của một lớp. Sử dụng chức năng miễn phí thay vì:

extern "C" { 
    __declspec(dllexport) int GiveMeNumber(int i) 
    { 
     return i; 
    } 
} 

Về phía quản lý thuộc tính DllImport của bạn là hoàn toàn sai. Không sử dụng SetLastError chỉ dành cho API Win32. Đừng bận tâm thiết lập CharSet nếu không có tham số văn bản. Không cần ExactSpelling. Và quy ước gọi là có lẽ là Cdecl.

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)] 
public static extern int GiveMeNumber(int i); 
+0

Cảm ơn, nó đã hoạt động. Nhưng nó không thể gọi một chức năng của một lớp học? (Đây là lần đầu tiên tôi sử dụng extern "C", tôi nghĩ rằng tôi luôn luôn cần phải xác định hàm trong lớp trong C++) –

+0

Bạn không cần định nghĩa một hàm trong một lớp trong C++. Các chức năng C cũ thời là tốt. –

0

Vấn đề là bạn đang khai báo hàm C++ "bên trong lớp C++ và đang yêu cầu P/Gọi sử dụng StdCall.

Cố gắng khai báo hàm C++ bên ngoài một lớp và xuất nó như bạn đã làm. Sau đó, mã của bạn sẽ hoạt động.

Nếu bạn thực sự phải có hàm C++ bên trong một lớp, hãy xem CallingConvention.ThisCall. Nhưng sau đó bạn có trách nhiệm tạo ra thể hiện lớp không được quản lý của mình và chuyển nó làm tham số đầu tiên của cuộc gọi P/Invoke của bạn

0

Tên điểm nhập của tệp dll được cung cấp trong tệp .exp được tìm thấy trong thư mục gỡ lỗi các tệp nguồn có mặt. Nếu dumpbin không hoạt động, bạn có thể thử điều này.