[DllImport("Kernel32.dll",
EntryPoint = "MoveFileW", // 實際匯出函數名 (支援重載/修飾名)
CharSet = CharSet.Unicode, // 字串編組:Unicode (W) / Ansi (A) / Auto
SetLastError = true, // 保留 Win32 錯誤碼 (Marshal.GetLastWin32Error)
CallingConvention = CallingConvention.StdCall, // 呼叫慣例:Win32 API 為 StdCall
ExactSpelling = true // 禁止自動尋找 A/W 後綴
)]
public static extern bool MoveFile(string src, string dst);
C++ 編譯器對函數名進行 Name Mangling (修飾),產生如 ?OpenSerialPort1@@YA_NXZ。解決方案:
extern "C" 禁用修飾:
// 輸出標準 C 風格符號
extern "C" __declspec(dllexport) bool OpenSerialPort1();
extern "C" __declspec(dllexport) bool fnGetIO(unsigned char* p1, unsigned char* p2, unsigned char* p3);
extern "C" __declspec(dllexport) bool CloseSerialPort1();
.def 模組定義檔匯出別名EntryPoint 直接寫原始函數名,CallingConvention = Cdecl (若 C++ 為 cdecl)| C/C++ 宣告 | C# 簽章 | 關鍵屬性 |
|---|---|---|
void GetData(byte* buf, int len) | void GetData(byte[] buf, int len) | 陣列自動編組為指標 (In/Out) |
void GetData(byte** buf) | void GetData(ref IntPtr buf) | 雙重指標用 ref IntPtr + Marshal.AllocHGlobal |
int GetValue(byte* pBuffer) (輸出陣列) | [DllImport] static extern int GetValue([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] byte[] buffer, int size); | Out + LPArray + SizeParamIndex 指定長度參數索引 |
void Func(char* str) (字串輸出) | void Func(StringBuilder sb, int capacity) | StringBuilder 為可變字串緩衝區 |
void Func(const char* str) (字串輸入) | void Func(string str) | 字串自動編組為 LPSTR/LPWSTR |
public class IniFile
{
private readonly string _path;
[DllImport("kernel32", CharSet = CharSet.Auto)]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32", CharSet = CharSet.Auto)]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public IniFile(string path) => _path = path;
public void Write(string section, string key, string value)
=> WritePrivateProfileString(section, key, value, _path);
public string Read(string section, string key, string defaultValue = "")
{
var sb = new StringBuilder(255);
GetPrivateProfileString(section, key, defaultValue, sb, 255, _path);
return sb.ToString();
}
}
Any CPU 在 64 位元 OS 執行為 64 位元進程,無法載入 32 位元 DLL。解法:專案屬性 → Build → 勾選 Prefer 32-bit 或編譯 64 位元版 DLLchar* (Ansi) 對應 CharSet.Ansi,wchar_t* 對應 CharSet.Unicode[StructLayout(LayoutKind.Sequential, Pack=4)] 控制封裝對齊,需與 C++ #pragma pack 一致