看板 C_and_CPP 關於我們 聯絡資訊
剛好我也什麼都不懂,討論一下。 ※ 引述《petercoin (彼得幣)》之銘言: < 恕刪 > : 在IO.h內定義一個struct如下 : typedef struct _ReadData : { : char *A; : int B; : ... : } READDATA; < 恕刪 > : 我目前想到的方法是重新在MyDll.h內定義一個名字不一樣但是內容一樣的struct : 例如 : typedef struct _ReadData1 : { : char *A; : int B; : ... : } READDATA1; 先提關鍵字 : dllexport , dllimport , 重點就這兩個 。 用同一份程式碼,配合 macro define 切換,以下贅述憑印象,請自行抓重點, 若有誤也請不吝指正。 -------------------------------------- 我不知道你用的 IDE / compiler 是哪套 , 只好以我比較熟的 visual studio 來講 , VS 到後面是以 solution 概念為主軸 , 一個 solution 可以有多個 project , 正常而言我的主程式 (exe) 會是其中一個 project , 命為 MainProj , 其他可能有數個產生 dll 的 project , 這些講其中一個 , 命為 IOProj。 在 IOProj 裡就是你放的 MyDll.h/.cpp , IO1.h/.cpp IO2.h/.cpp 正常共用 (其他 proj 也用得到) 的 struct/class 宣告, 應是抽出來集中放到一個 .h 裡面,然後宣告時動了點手腳 , 以下是範例 // ---------- myio.h ---------- #pragma once #ifndef EXPORT_IO_API #define IO_API __declspec ( dllimport ) #else #define IO_API __declspec ( dllexport ) #endif struct IO_API IOData { unsigned int m_addr; unsigned char m_val; }; int IO_API set_data(IOData * pdata) ; // implement in myio.cpp // ---------- myio.cpp ---------- // #include "stdafx.h" // for vs #include "myio.h" int IO_API set_data( IOData * pdata ) { if(pdata == NULL) return 0; pdata->m_addr = 0x80000000; pdata->m_val = 0xCC; return 1; } 先分析一下 .h 講的東西, 若不定義 EXPORT_IO_API , 便可將 IODATA 與其他 function import (Main Project); 若定義出 EXPORT_IO_API , 便可將 IODATA 與其他 function export (IO Project); 這時候就借用了 VS IDE 的巨集定義功能, 在 IO Project 之專案屬性->組態屬性->c/c++->前置處理,前置處理定義新增一個 EXPORT_IO_API 即可,這個 header 對 IO Project 而言就是做 dll export ; 若你習慣用 command line 編譯或是 IDE 不支援前置處理設定的話, 大概就是從 compiler command line 那裡做前置處理了,詳細略(還不是因為懶得查XD)。 而在 Main Project ,只需要 include 到 myio.h 即可 , 而且確保 EXPORT_IO_API 是沒被定義過的就行了 (正常應該是不會,除非衝名) include 方式有很多種,像是 #include "..\\IO\\myio.h" , 或是直接在 IDE 裡面做額外的 include 目錄都行。 這種方式的好處是,最後的確只需要維護一份 .h / .cpp 便可, 不會因為 Project 不同,導致 myio.h , myio.cpp 到處亂飛, 多了兩個問題變成是專案相依性 與常看到 "無法解析的外部符號 @XY ..... " 等等, 不過這兩個問題應該是你原本架構都有機會遇到的。 以上,若我敘述有誤,請不吝指定。 或有其他較佳之維護方式,也歡迎提出討論。 -- 「自從我學了 C# , 人都變聰明 , 考試都考一百分」 「自從我學了 VB , 皮膚都變好 , 人也變漂亮了 」 「自從我學了 Java , 明顯變壯 , 個子也變高了 」 「自從我學了 C++ , 內分泌失調 , 頭都禿了... 」 < Kuso 星爺語錄 > -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.169.158 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1435165717.A.A92.html
petercoin: 意思是說只要有dllexport的struct 就算不放在IO.h 06/25 09:13
petercoin: 而只放在MyDll.h 一樣可以直接在IO.cpp裡面使用是嗎? 06/25 09:14
petercoin: 我目前是用VC 但是exe跟dll是不同solution 06/25 11:24
petercoin: MyDll.cpp只提供Set或Get的介面 功能的實作在IO.cpp 06/25 11:25
petercoin: 所以才會有struct要共用的問題QQ 06/25 11:25
uranusjr: 這是正解, 然後樓上你需要的應該是宣告在 IO.h, 然後在 06/25 11:50
uranusjr: MyDLL.h 加上 #include "IO.h" 06/25 11:50
Feis: 其實重點就是在於 MyDLL.h 要不要 include 其他人的問題 06/25 12:07
Feis: 跟這篇的重點其實不太一樣. (我是說原 po 的疑問) 06/25 12:08
Feis: 要 include 的話, 就不會有原 po 的問題. 06/25 12:08
Feis: 接著才是 dllimport 跟 dllexport 的問題 06/25 12:08
Feis: 還是說其實是我理解有問題 Orz.. 06/25 12:09
petercoin: 其實我的問題是如果寫在IO.h 那使用dll的人如何知道 06/25 12:23
petercoin: 這個struct的內容有什麼? 06/25 12:23
petercoin: 因為我只打算把MyDll.h丟給使用者 不打算公開IO.h 06/25 12:24
Feis: 我理解阿. 你要 include 其他人就是要把其他人拿進來 06/25 12:25
Feis: 你不想的話要怎麼辦. 這才是你的問題. 06/25 12:26
Feis: 我的意見就是要嘛把 A.h 給別人. 要嘛就包起來 06/25 12:27
petercoin: 還是乾脆把STRUCT寫成註解放在MyDll.h...XD 06/25 12:27
Feis: 如果你連 A.h 都不想給別人. 那要說明一下理由 06/25 12:27
Feis: 寫成註解有甚麼意義嗎 ? 06/25 12:28
petercoin: 因為我只想讓使用者知道有什麼function可以用 但是我不 06/25 12:30
petercoin: 想讓他知道其他在實作上的任何相關內容 所以才不想放 06/25 12:30
petercoin: 額外的檔案出去QQ 06/25 12:30
Feis: A.h 不是只有共用的 struct 嗎 ? 06/25 12:31
Feis: 還是你連 struct 內部有甚麼成員都不想讓別人知道 ? 06/25 12:31
petercoin: 阿不好意思 我把A.h跟IO.h搞混了 照你的意思就是把 06/25 12:31
petercoin: 共用的struct放A.h裡面 最後把A.h跟MyDll.h都丟給使用 06/25 12:32
Feis: 我以為之前那篇就是這意思 XD 06/25 12:32
petercoin: 者 然後MyDll.h裡面include A.h這樣對吧? 06/25 12:32
petercoin: 上一篇你回的我有看懂啦 只是剛剛一時之間沒切換過來 06/25 12:33
Feis: 然後你還需要看一下這篇了解一下 dllimport 跟 dllexport 06/25 12:33
petercoin: 了解 不過IO_API加在struct上的用意其實我不是很了解QQ 06/25 12:37
Feis: 那你先研究一下 DLL 是怎麼運作的. 06/25 12:37
petercoin: 了解 目前也只是寫出可以用的 但是運作還不是很熟悉 06/25 12:41
petercoin: 整個是被公司趕鴨子上架要做出成品Orz 06/25 12:42
Feis: 不要被煮熟就好~ 06/25 12:43
petercoin: 會繼續努力研究 有問題再來勞煩大家了!! 06/25 12:58
EdisonX: 額 原來我又跑題了 orz 06/25 15:08
petercoin: E大 不會啦 你剛好提到一個我沒有注意過的 我會研究 06/25 15:15
petercoin: 研究看這中間的差別是什麼 06/25 15:15
uranusjr: 其實還有一個方法是用 opaque pointer,DLL 只提供一個 06/25 15:40
uranusjr: READDATA * 宣告, 然後提供 function 讀寫所有欄位內容 06/25 15:41
uranusjr: 這樣 DLL 使用者就根本不需要知道 struct 內容了 06/25 15:41