Interop C++ dll from vb.net

How to marshal C++ dll from vb.net

Page 1 of 1

4 Replies - 8441 Views - Last Post: 17 November 2009 - 04:38 AM Rate Topic: -----

#1 ggoutam7  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 26-September 08

Interop C++ dll from vb.net

Post icon  Posted 12 November 2009 - 10:16 PM

Hi,

I am writing this only after exhausting effort to search and find the solution was unsuccessful.

I am using Visual Studio 2005. The Test123 function written in C++ should be called from vb.net by using Interop Services.
The Testing.dll is a CLR dll.

Below is a simplified version of the C++ structure :

typedef struct TEST_STRUCT
{
   long lTotal;
   int nRow;
   int nCol;
   CString sName;
   BOOL bFound;
	  int item[100];
} TEST;


Below is a simplified version of the structure declared in vb.net :

<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _
	Public Structure TEST_STRUCT
		' ''<System.Runtime.InteropServices.FieldOffsetAttribute(0)> _
		Public lTotal As Integer
		Public nRow As Integer
		Public nCol As Integer
		<System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)> _
		Public sName As String
		<System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> _
		Public bFound As Boolean

		'<System.Runtime.InteropServices.MarshalAsAttribute _
		'(System.Runtime.InteropServices.UnmanagedType.SafeArray, SafeArraySubType:=Runtime.InteropServices.VarEnum.VT_I4)> _
		<System.Runtime.InteropServices.MarshalAsAttribute _
		(System.Runtime.InteropServices.UnmanagedType.LPArray, SizeConst:=100)> _
			Public Item() As Integer
	End Structure

	Public Declare Auto Function Test123 Lib "Testing.dll" () As TEST_STRUCT
	


What can work :
1) I can call the module Test123 from vb.net and it can run.
2) I can interop data for lTotal, nRow and nCol and receive at vb.net without any problem.

What my questions are :
1) How to interop data for sName, bFound and item[100]?
2) Which part I am wrong?
3) How should I declare the structure in vb.net to interop these data?
4) Can Interop support CString directly?
5) Is there any indirect way of marshaling which can work, such as doing the Interop in C# and then call from vb.net?

Your guidance on solving this problem is very much appreciated.

Thanks,
Goutam

Is This A Good Question/Topic? 0
  • +

Replies To: Interop C++ dll from vb.net

#2 crepitus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 84
  • View blog
  • Posts: 383
  • Joined: 08-September 09

Re: Interop C++ dll from vb.net

Posted 13 November 2009 - 06:38 AM

View Postggoutam7, on 12 Nov, 2009 - 09:16 PM, said:

What my questions are :
1) How to interop data for sName, bFound and item[100]?
2) Which part I am wrong?
3) How should I declare the structure in vb.net to interop these data?
4) Can Interop support CString directly?
5) Is there any indirect way of marshaling which can work, such as doing the Interop in C# and then call from vb.net?


1) bFound and item look ok, they fail because the CString field isn't working, and they come after it.
2) See 4.
3) Not sure.
4) no.
5) Do the interop in C++/CLR and call from VB.Net maybe. This is called C++ interop (implicit pinvoke) - this might help: "overview of marshaling in C++" http://msdn.microsof...y/bb384865.aspx

You'll have to search how to marshal a CString.

Do the other two fields work if you marshal the CString as an IntPtr?

This post has been edited by crepitus: 13 November 2009 - 09:40 AM

Was This Post Helpful? 0
  • +
  • -

#3 ggoutam7  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 26-September 08

Re: Interop C++ dll from vb.net

Posted 16 November 2009 - 01:54 AM

Hello Mr. Crepitus,

Thank you for your prompt reply and interest in this topic.

When I do the testing, I comment out all and test one by one as below. When I can interop every value I need, only then I will put them together :

typedef struct TEST_STRUCT
{
   //long lTotal;
   //int nRow;
   //int nCol;
   //BOOL bFound;
   int item[100];
   //CString sName;
} TEST;


extern "C" __declspec(dllexport) TEST_STRUCT Test123();

extern "C" __declspec(dllexport) TEST_STRUCT Test123()
{
	//CString sTemp = "You got the CString";
	TEST_STRUCT TestStruct;

	//TestStruct.lTotal  = 7;
	//TestStruct.nRow  = 20;
	//TestStruct.nCol  = 30;
	//TestStruct.sName  = "You got the CString";
	//TestStruct.bFound  = false;
	TestStruct.item[0] = 11; 

	return TestStruct;
}


I could not interop bFound if I try to receive as boolean in vb.net. If I declare the bFound as int16 at the vb.net side, then I can receive 0 or 1. But that's not what we need.

1. As I comment them all and interop one by one, the possibility for them to clash is minimum. After each of them transferable, I will put them together. As per your advice, I plan to put CString at the last.

5. Please enlighten me on the IntPtr, as I am still not sure how to use it in this case. I could not find IntPtr in vb.net UnmanagedType members.

I still could not interop sName, bFound and item[100]. I am getting error message "Method's type signature is not PInvoke compatible."
Any help will be amazing...

cheers,
Goutam
Was This Post Helpful? 0
  • +
  • -

#4 crepitus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 84
  • View blog
  • Posts: 383
  • Joined: 08-September 09

Re: Interop C++ dll from vb.net

Posted 16 November 2009 - 02:16 PM

So, you can alter the C++ dll?

I know very little C++. You could try asking in the C++ forum, or ask on the MSDN forums, where there are a couple of gurus at this stuff...

In the windows API, you never get a Struct returned by a function, instead you pass the structures as parameters. I think this is why it is failing. If you use this C++:

typedef struct TEST_STRUCT
{
  long lTotal;
  int nRow;
  int nCol;
  BOOL bFound;
  int item[100];

} TEST_STRUCT;


extern "C" __declspec(dllexport) void Test123(TEST_STRUCT* s);

extern "C" __declspec(dllexport) void Test123(TEST_STRUCT* s)
{
   s->lTotal  = 7;
   s->nRow  = 20;
   s->nCol  = 30;
   s->bFound  = true;
   s->item[0] = 11; 
}


And this VB.Net:

	<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
	Public Structure TEST_STRUCT
		Public lTotal As Integer
		Public nRow As Integer
		Public nCol As Integer
		<MarshalAs(UnmanagedType.Bool)> _
		Public bFound As Boolean
		<MarshalAs(UnmanagedType.ByValArray, SizeConst:=100, ArraySubType:=UnmanagedType.I4)> _
		Public Item() As Integer
	End Structure

	<DllImport("C:\Users\SEP\Documents\Visual Studio 2008\Projects\test2\Release\test2.dll")> _
	Public Shared Sub Test123(ByRef struc As TEST_STRUCT)
	End Sub


Then it works, but I've not used that CString, as they aren't supported by P/Invoke. Can you use a different String type in the C++?
Was This Post Helpful? 0
  • +
  • -

#5 ggoutam7  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 26-September 08

Re: Interop C++ dll from vb.net

Posted 17 November 2009 - 04:38 AM

Hi,

Yes. I can alter the C++ code. The C++ program is huge and I don't intend to burden the readers with the code. So, I provided a simplified version of the structure.

Two of the interop function calls are passing in structure as parameters and one of them returns a structure (if I am to change, it should return an integer array). If I can solve this simple one i.e. Test123, I believe I can solve the rest.

Regarding the CString, I absolutely agree with you and considering to use BSTR. And I also have to think twice before changing to other types, as it involves a lot of changes. CString really made it easy on the C++ string manipulation problems. I do encourage C++ programmers to use CString :
CString is a boon for C++ programmers


I am sorry to say that I am not making much progress. I wonder if the problem is some where else and I am touble shooting at some where else.

If I create an MFC Active X control, it automatically creates DllRegisterServer and DllUnregisterServer modules, to register to regedit by using regsvr32.
When I create this CLR dll, DllRegisterServer and DllUnregisterServer modules are not created automatically. And, I can't register this dll.

Is it a must to register a dll by using regsvr32?

Well, I am trying to look at the problem from other angels...just to make sure I am not missing anything.

cheers,
Goutam
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1