2013-10-04 48 views
0

好吧,我正在嘗試爲可以使用GetProcAddress調用的另一個應用程序創建運行時DLL。C++/CLI DLL鏈接器問題

因此,我在VS2012 C++ Express(Header和源代碼下面)中構建了DLL,即使當dll與exe位於同一文件夾中時,它也會返回NULL。所以這導致我相信dllmain函數存在一個問題。於是,我開始尋找通過MSDN,發現下面的鏈接

http://msdn.microsoft.com/en-us/library/vstudio/988ye33t.aspx

它指出,它已經採取了照顧我,當我創造,我做到了以下這個MSDN鏈接DLL模板。

http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx

所以我決定嘗試建立在釋放模式的DLL(思考一些事情,這可能是這個問題),但我得到一個鏈接錯誤說法入口點必須明確。它在調試模式下可以正常工作,但不能在發佈模式下工作。我認爲我錯過了一些簡單的東西。

Error 1 error LNK1561: entry point must be defined C:\Users\ProRip\Documents\Visual Studio 2012\Projects\PhantomAdapter\AdapterDLL\LINK AdapterDLL 

#ifdef PHANTOMADAPTER_EXPORTS 
#define PHANTOMADAPTER_API __declspec(dllexport) 
#else 
#define PHANTOMADAPTER_API __declspec(dllexport) 
#endif 
#using <mscorlib.dll> 
#using <system.dll> 
using namespace System; 
using namespace System::IO::Ports; 
using namespace System::Threading; 
namespace PhantomAdapter 
{ 


class PhantomAdapter 
{ 
public: 
    static PHANTOMADAPTER_API int open(); 
    static PHANTOMADAPTER_API int close(); 
    //static PHANTOMADAPTER_API double init(bool); 
    //static PHANTOMADAPTER_API int noDevices(); 
    static PHANTOMADAPTER_API int angle(double& angle); 
    static PHANTOMADAPTER_API int torque(double torque); 
    static PHANTOMADAPTER_API int ready(); 
}; 
public ref class SerialPort 
{ 
private: 
    static System::IO::Ports::SerialPort^ p1; 
public: 
    static int openPort(); 
    static void closePort(); 
    static int read(); 
    static void send(Byte data); 
    static int check(); 
}; 

}

來源

#include "stdafx.h" 


#include "stdafx.h" 
#include "PhantomAdapter.h" 
#include <stdexcept> 

using namespace std; 



namespace PhantomAdapter 
{ 

    int PhantomAdapter::open() 
    { 
     int flag=0; 

     flag=SerialPort::openPort(); 
     return flag; 

    } 

    int PhantomAdapter::close() 
    { 
     SerialPort::closePort(); 

     return 1; 
    } 

    int PhantomAdapter::angle(double& angle) 
    { 
     SerialPort::send(0x82); 
     angle = (SerialPort::read() * 255) + (SerialPort::read()); 
     angle = angle*(6.2832/512); 

     return 1; 
    } 

    int PhantomAdapter::torque(double torque) 
    { 
     return 1; 
    } 

    int PhantomAdapter::ready() 
    { 
     return SerialPort::check(); 
    } 

    int SerialPort::openPort() 
    {  
     bool check=0; 
     p1 = gcnew System::IO::Ports::SerialPort(); 

     p1->BaudRate = 57600; 
     p1->PortName = "COM3"; 
     if(p1->IsOpen) 
      return 0; 
     else { 
      p1->Open(); 
      return 1; 
     } 

    } 

    int SerialPort::check() 
    { 
     array<String^>^ serialPorts = nullptr; 
     int flag=0; 
     serialPorts = p1->GetPortNames(); 

     for each(String^ port in serialPorts) 
     { 
      if(port=="COM3") 
       flag=1;    
     } 

     return flag; 
    } 

    void SerialPort::closePort() 
    { 
     p1->Close(); 
    } 

    void SerialPort::send(Byte data) 
    { 
     array<unsigned char>^ buffer = gcnew array<Byte>(1); 

     buffer[0] = (char)data; 
     p1->Write(buffer,0,1); 
    } 

    int SerialPort::read() 
    { 
     return p1->ReadByte(); 
    } 
} 
+2

這不是C++,這是一種名爲C++/CLI的CLR語言。 –

回答

1

在你的VS項目,你可以檢查設定:
1. Configuration Properties > General > Configuration Type?如果是釋放模式,是否設置爲.dll
2. Configuration Properties > Linker > System > SubSystem?這兩種模式相同嗎?

+0

謝謝我剛剛意識到它已在發佈模式下設置爲'.exe',但仍不能解釋爲什麼我無法使用'loadlibrary'成功調用它。你有什麼想法,嘗試regsrv32,它說它已加載,但沒有找到'DllRegisterServer'。我知道我不需要regsvr32它,如果它在同一目錄中,但想看看它是否成功加載它。 – codem

+0

在調試模式下,你是否面臨同樣的問題(不是成功的'loadlibrary')?或僅在發佈模式? – lolando

+0

兩個我試圖釋放模式,看看它是否有所作爲,但它沒有 – codem

0

您無法通過LoadLibrary/GetProcAddress從本機代碼調用.NET方法(並且C++/CLI方法是.NET方法)。 .NET方法和類不以那種方式導出。你將總是得到一個NULL指針。

你可以做什麼:

  • 寫在.NET中的COM組件用標準C++調用.NET代碼

  • 出口正常,普通的C++方法引用僅在內部

  • 通過使用Assembly類及其方法將受管dll導入托管的(相同的C++/CLI或C#或任何其他.NET語言)可執行文件。

+0

「普通的C++方法」根本不是方法,它們是*函數*。C++沒有方法,只有「虛擬的非靜態成員函數」可以合理地稱爲「方法」。 –

+0

@BenVoigt那些將不會出口,因爲...? – nvoigt

+0

因爲輸出除全局函數之外的任何東西都是絕對的災難。非靜態成員函數需要一個目標對象,它只能由一個對象創建表達式創建,該對象創建表達式涉及構造函數調用等構造函數 - 構造函數從來不打算獨立調用,其他的東西沒有可移植的方式來重現。然後你會遇到名稱問題。只是不要嘗試導出成員函數。從C++外部調用虛擬成員函數的方法是使用vtable(由COM組件項目符號覆蓋)。 –