1

I've a C# DLL below like. I want to use this C# DLL in C++ Builder.

But I don't know C# Struct and C++ Struct marshalling:

using RGiesecke.DllExport; using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace TestLibrary { [ComVisible(true)] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MyStruct { public int X; public int Y; } public class Class1 { [DllExport("DoSomething", CallingConvention = CallingConvention.StdCall)] public static int DoSomething(int x, int y, ref MyStruct myStruct) { myStruct.X = 50; myStruct.Y = 75; return x + y; } } } 

I want to pass "myStruct" parameter from C++ Builder below like.

void __fastcall TForm1::FormCreate(TObject *Sender) { struct MyStruct { int X; int Y; }; int (__stdcall *DoSomething)(int,int,MyStruct); HINSTANCE dllHandle = NULL; dllHandle = LoadLibrary( edtdllPath->Text.c_str()); if(dllHandle == NULL) return; int status = -1; try { DoSomething =(int (__stdcall *)(int,int,MyStruct)) GetProcAddress(dllHandle, "DoSomething"); } catch(Exception &Err) { ShowMessage(Err.Message); } if(DoSomething != NULL) { try { MyStruct myStruct; status = DoSomething(5,5,myStruct); String strStatus = status; ShowMessage(strStatus); ShowMessage(myStruct.X); ShowMessage(myStruct.Y); } catch(EAccessViolation &err) { ShowMessage(err.Message); } } } 

When I debug code,myStruct.X and myStruct.Y value is wrong.

Where is my wrong ?

9
  • 1
    The string is a big problem. You can't use ref StringBuilder, and I don't think you can use StringBuilder. By far the easiest solution is to use UnmanagedType.BStr and use the COM BStr. You do need to back up a little and understand the basics more than you currently do. Commented Sep 10, 2015 at 13:20
  • thanks for interest @DavidHeffernan. I've checked StringBuilder parameter.it's working. Not worked only myStruct parameter. Commented Sep 10, 2015 at 13:55
  • No, the string builder can't be working. Ask yourself who's going to deallocate the memory? For starters. There are more problems. You are mistaken. Commented Sep 10, 2015 at 13:59
  • thanks @DavidHeffernan ur guru Commented Sep 11, 2015 at 8:39
  • I've added adress to X like that. struct MyStruct { int *X; double *Y; }; I get value of "myStruct.X" as true below like. ShowMessage(*myStruct.X); But value of *myStruct.X wrong. Commented Sep 11, 2015 at 11:00

2 Answers 2

3

You are not passing your struct as pointer to c#, yet in c# you told that it would be a pointer (ref).

Sign up to request clarification or add additional context in comments.

Comments

1

The C# project declares the struct parameter like this:

ref MyStruct myStruct 

That marshals as a pointer to the struct. In C++ that means

MyStruct* 

So change the declaration of the function pointer variable to be like so:

int (__stdcall *DoSomething)(int,int,MyStruct*); 

And use the same type when you cast:

DoSomething =(int (__stdcall *)(int,int,MyStruct*)) GetProcAddress(dllHandle, "DoSomething"); 

Note that a typedef would serve you better here to avoid repeating yourself. And note also that GetProcAddress does not raise exceptions. It signals errors by returning NULL. You don't check for errors properly.

When you call the function pass the address of the struct:

status = DoSomething(5,5,&myStruct); 

It's also a little pointless to declare status and initialise it to -1, but then overwrite that value later. It would be more idiomatic to declare and initialise it like this:

int status = DoSomething(5,5,&myStruct); 

7 Comments

I get error that line status = DoSomething(5,5,&myStruct); [C++ Error] Unit1.cpp(63): E2034 Cannot convert 'MyStruct * *' to 'MyStruct *' But when I removed that & character compiled. Thank you for everything @David
That's because you've changed the code from that in the question. You declared MyStruct *myStruct which is a mistake.
When I add more than 2 fields to struct then throwing EAccessViolation exception. What's can be source of problem ? How can I debug this problem ? --------------------------- Debugger Exception Notification --------------------------- Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address CCCCCCCD. Read of address CCCCCCCD'. Process stopped. Use Step or Run to continue. --------------------------- OK Help ---------------------------
You're rigth. I have add only int Z named field like that. struct MyStruct { int X; double Y; int Z; };
That's only half of the code. The C# code matters too. For some reason you packed the C# struct, but not the C++ struct. Packing is not recommended. It results in misalignment of the data. Why did you decide to pack?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.