By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,750 Members | 1,231 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,750 IT Pros & Developers. It's quick & easy.

AccessViolationException - passing Structures between Unmanaged and Managed Code

P: 6
I have a problem trying to pass a structure to an unmanaged c++ DLL from C#. When I call PCSBSpecifyPilotLogon from C#, it throws an AccessViolationException
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
This is what I have...

The exported C++ DLL Function;

Expand|Select|Wrap|Line Numbers
  1. __declspec(dllexport) void PCSBSpecifyATCLogon(PCSBSessionID, const char * inServer, unsigned short inPort, const char * inID, const char * inPassword, const PCSBATCConnection_t * inInfo);
And the C++ structure;
Expand|Select|Wrap|Line Numbers
  1. typedef struct 
  2. {
  3. const char * callsign; 
  4. const char * name; 
  5. PCSBRating rating;
  6. } PCSBATCConnection_t;
The PCSBRating is just an Enum.

In C# I want to call the function to the unmanaged C++ DLL;
Expand|Select|Wrap|Line Numbers
  1. [DllImport("PCSB.dll")]
  2. private static extern void PCSBSpecifyATCLogon(IntPtr SessionID, string ServerAddr, ushort Port, string ID, string Password, [MarshalAs(UnmanagedType.Struct)] PCSBATCConnection ATC);
And the C# Structure; ... Even tried using MarshalAs, with no success.

Expand|Select|Wrap|Line Numbers
  1. [StructLayout(LayoutKind.Sequential)]
  2.         public struct PCSBATCConnection
  3.         {
  4.             //[MarshalAs(UnmanagedType.LPTStr)]
  5.             public string callsign;
  6.             //[MarshalAs(UnmanagedType.LPTStr)]
  7.             public string name;
  8.             [MarshalAs(UnmanagedType.U4)]
  9.             public PCSBATCRating rating;
  10.         }
It would be greatfull if somebody could spot what I am doing wrong...

Many thanks

Craig
Mar 17 '09 #1
Share this Question
Share on Google+
5 Replies


tlhintoq
Expert 2.5K+
P: 3,525
While the C++ Dll issue is out of my area I just wanted to acknowledge how nice it is to see someone post such a complete, well worded message, with great use of both [quote] and [code] tags. And only your second post too! Great example to others.

By the way, I do notice that the C++ function is expecting pointers for some things...
Expand|Select|Wrap|Line Numbers
  1. const char * inServer
but you are calling it by passing it a string variable instead of a pointer to a character array.
Expand|Select|Wrap|Line Numbers
  1. string ServerAddr
so I'm going to guess that your real string is being interpreted as the address of a memory space to a character array and that is going South on ya'
Mar 17 '09 #2

P: 6
Hehe you wouldn't believe how long it took to write. I hope its clear enough. I use a similar function without structures, that passes strings and numbers fine. Its just when I pass structures that it comes up with the Exception. Does it have something to do with the way the struct is Marshalled?

Having made a test program to send an unmanaged struct to a c++ function, it works, but I am still confused as to why it doesnt work in the program I want it to. Is it because I am using multiple instances of the class?

Craig
Mar 17 '09 #3

tlhintoq
Expert 2.5K+
P: 3,525
Good or bad is a matter of perspective, but I'm not having to deal with legacy C++ DLL's from earlier versions. Instead I have been given free range to write everything new, fresh from scratch.

The only places I've dealt with DLL issues is for hardware from vendors and I've been lucky enough to not have to deal with marshalling at all.

Anyone else reading this with more experience at it please jump in.
Mar 17 '09 #4

alexgm23
P: 6
Hi Craig,

I hope this can be useful for you:

DLL Code
Expand|Select|Wrap|Line Numbers
  1. // msgbox.dll
  2.  
  3. typedef struct MsgBoxData
  4. {
  5.     const char * Text;
  6.     int Options;
  7. } ExchStruct;
  8.  
  9. extern "C" __declspec(dllexport) void MsgBox(const char * Title, const MsgBoxData * Data);
  10.  
  11. void MsgBox(const char * Title, const MsgBoxData * Data)
  12. {
  13.     MessageBox(NULL, Data->Text, Title, Data->Options);
  14. }
  15.  
C# Code
Expand|Select|Wrap|Line Numbers
  1. public partial class Form1 : Form
  2. {
  3.     public Form1()
  4.     {
  5.         InitializeComponent();
  6.     }
  7.  
  8.     [StructLayout(LayoutKind.Sequential)]
  9.     public struct MsgBoxData
  10.     {
  11.         public IntPtr Text;
  12.         public Int32 Options;
  13.     }
  14.  
  15.     [DllImport("msgbox.dll", CallingConvention = CallingConvention.Cdecl)]
  16.     public extern static void MsgBox(
  17.         [MarshalAs(UnmanagedType.LPStr)] String Title,
  18.         [MarshalAs(UnmanagedType.SysInt)] IntPtr Data
  19.         );
  20.  
  21.     private void button1_Click(object sender, EventArgs e)
  22.     {
  23.         MsgBoxData msg = new MsgBoxData();
  24.         msg.Text = Marshal.StringToHGlobalAnsi(textBox2.Text);
  25.         msg.Options = 0;
  26.         IntPtr ptrmsg = Marshal.AllocHGlobal(Marshal.SizeOf(msg));
  27.         Marshal.StructureToPtr(msg, ptrmsg, true);
  28.         MsgBox(textBox1.Text, ptrmsg);
  29.     }
  30. }
  31.  
  32.  
If you need to pass a struct pointer as a parameter you need to allocate som memory for it first:

Expand|Select|Wrap|Line Numbers
  1.     IntPtr ptrmsg = Marshal.AllocHGlobal(Marshal.SizeOf(msg));
  2.     Marshal.StructureToPtr(msg, ptrmsg, true);
  3.  
Alex G.
Mar 17 '09 #5

P: 6
Hey, that works, thanks Alex! I only had to allocate the structure in memory. However I have a new problem... which I shall start a new thread... regarding callbacks and garbage colllection.

Craig
Mar 18 '09 #6

Post your reply

Sign in to post your reply or Sign up for a free account.