[編輯]我改變了由Stephen Martin建議的源代碼(以粗體突出顯示)。並添加了C++源代碼。從C#調用非託管代碼 - 返回一個數組的結構
我想在自寫的C++ dll中調用一個非託管函數。該庫讀取機器的共享內存以獲取第三方軟件的狀態信息。由於有幾個值,我想返回結構中的值。但是,在結構中有char []
(具有固定大小的char數組)。我現在嘗試接收結構從DLL調用是這樣的:
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_OUTPUT
{
UInt16 ReadyForConnect;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
String VersionStr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
String NameOfFile;
// actually more of those
}
public partial class Form1 : Form
{
public SYSTEM_OUTPUT output;
[DllImport("testeshm.dll", EntryPoint="getStatus")]
public extern static int getStatus(out SYSTEM_OUTPUT output);
public Form1()
{
InitializeComponent();
}
private void ReadSharedMem_Click(object sender, EventArgs e)
{
try
{
label1.Text = getStatus(out output).ToString();
}
catch (AccessViolationException ave)
{
label1.Text = ave.Message;
}
}
}
我將發佈從C++ DLL的代碼,以及,我敢肯定有更多的追捕。原結構STATUS_DATA
有一個結構SYSTEM_CHARACTERISTICS
的四個實例的數組,並且在該結構中有char[]
s,它們尚未被填充(導致),導致錯誤的指針。這就是爲什麼我試圖提取STATUS_DATA
中第一個SYSTEM_CHARACTERISTICS
項目的子集。
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#if defined(_MSC_VER)
#include <windows.h>
#define DLL extern "C" __declspec(dllexport)
#else
#define DLL
#endif
using namespace std;
enum { SYSID_LEN = 1024, VERS_LEN = 128, SCENE_LEN = 1024 };
enum { MAX_ENGINES = 4 };
struct SYSTEM_CHARACTERISTICS
{
unsigned short ReadyForConnect;
char VizVersionStr[VERS_LEN];
char NameOfFile[SCENE_LEN];
char Unimplemented[SCENE_LEN]; // not implemented yet, resulting to bad pointer, which I want to exclude (reason to have SYSTEM_OUTPUT)
};
struct SYSTEM_OUTPUT
{
unsigned short ReadyForConnect;
char VizVersionStr[VERS_LEN];
char NameOfFile[SCENE_LEN];
};
struct STATUS_DATA
{
SYSTEM_CHARACTERISTICS engine[MAX_ENGINES];
};
TCHAR szName[]=TEXT("E_STATUS");
DLL int getStatus(SYSTEM_OUTPUT* output)
{
HANDLE hMapFile;
STATUS_DATA* pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_READ, // read access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return -2;
}
pBuf = (STATUS_DATA*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return -1;
}
output->ReadyForConnect = pBuf->engine[0].ReadyForConnect;
memcpy(output->VizVersionStr, pBuf->engine[0].VizVersionStr, sizeof(pBuf->engine[0].VizVersionStr));
memcpy(output->NameOfFile, pBuf->engine[0].NameOfFile, sizeof(pBuf->engine[0].NameOfFile));
CloseHandle(hMapFile);
UnmapViewOfFile(pBuf);
return 0;
}
現在我得到一個空output
結構和返回值IST不爲0的預期。這是一個不斷變化的數字,有七位數字,這讓我感到困惑......我搞砸了DLL嗎?如果我讓非託管代碼可執行並調試它,我可以看到,output
正在填充適當的值。
我編輯了帖子和來源以符合您的建議。還發布了非託管代碼的片段。 – rdoubleui 2009-11-07 12:23:24
我有沒有提到我仍然不知道爲什麼它不起作用? – rdoubleui 2009-11-13 13:32:15