Click here to Skip to main content
15,067,335 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I want to be a C ++ DLL for C # call and return list, type is a structure defined
c ++ The structure is;
struct mailInfo
    const char *mailFrom;
    const char *mailReceivers;
    const char *mailDate;
    const char *mailTitle;
    const char *mailBody;

C ++ code is:

extern "C" __declspec(dllexport)  vector<mailInfo> rData(char module_path[],char tableName[])
   mailInfo mailIo;
   int  result = sqlite3_open(((string)module_path+"\\mail.db").c_str(), &conn);  
	if (!result)  
		sqlite3_stmt *stat;  
		const char *pzTail = NULL;  
		sqlcommand="select * from "+(string)tableName+";";
		sqlite3_prepare(conn, sqlcommand.c_str(), -1, &stat, &pzTail);  
		int nColumn = sqlite3_column_count(stat);  		
		result = sqlite3_step(stat);
		while (result == SQLITE_ROW) /* sqlite3_step() has another row ready */  
			//*(p+1) = '\0';  
			mailIo= outputItem(stat, nColumn, module_path); 
			/*mInfo.mailFrom= (const char*)sqlite3_column_text(stat,2);
			string ss=mInfo.mailFrom;
			cout << endl;  
			result = sqlite3_step(stat);  
    return mInfoList;  

The structure is defined in C #:
public struct mailInfo

    /// char*
    public byte[] mailFrom;

    /// char*
    public byte[] mailReceivers;

    /// char*
    public byte[] mailDate;

    /// char*
    public byte[] mailTitle;

    /// char*
    public byte[] mailBody;

[DllImport(&quot;my.dll&quot;, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern List&lt;mailInfo&gt; rData(byte[] dbPath, byte[] TBFullName);

Code C # call is;
List<loadDLL.mailInfo> ml = new List<loadDLL.mailInfo>();
byte[] bTN = Encoding.Default.GetBytes(TN);
byte[] bdbPath = Encoding.Default.GetBytes(Form1.datePath + emailFromAddress);
loadDLL.rData(bdbPath, bTN);

But when I run debug, the following tips:
Unable to marshal "return value": unable to marshal the generic type.
I wonder how to return list data from C ++, thank you!
Updated 15-Aug-15 19:33pm
George Jonsson 16-Aug-15 1:36am
You could try to return a regular pointer to an array instead of a list.
Or try a CComSafeArray.

This wont work because, the C++ runtime cant allocate memory for the C# runtime. So you need to provide the string buffer for C++.

Maybe you can use a struct with static buffers like:
struct mailInfo
    byte mailFrom[50];

If it doesnt work, than make a "formatted string" and parse it C#.

//split in C#
String[] mailInfo = s.Split('\n');
In addition to solution 1, you can also use C++/CLI to make the bridge either in the same assembly or an additional one.

In that case, you can create the managed structure from C++/CLI code and it is then much easier to do any required conversion if you go outside of P/Invoke capabilities.

By the way, all strings in both side should ideally be Unicode.

Having byte[] on C# side for strings does not make any sense at all.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900