作者EdisonX (卡卡獸)
看板C_and_CPP
標題Re: [問題] 自製DLL的struct問題
時間Thu Jun 25 01:08:24 2015
剛好我也什麼都不懂,討論一下。
※ 引述《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