473,507 Members | 2,430 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Memory Allication (Managed VC++ DLL to Unmanaged DLL) [Second Try]

(Sorry for spamming multiple groups, But I need a solution to this problem)

I think this should be a simple question on Memory Allocation in a managed DLL and passing a memory pointer over to an unmanaged DLL.

I have a "Unmanaged" Client DLL that I'm creating a Managed "wrapper" to be used in VB.Net and/or C#..

In the my Client DLL (unmanaged), There are several functions where I need to allocate a "client side" memory buffer to marshall data into from the server side of the application.

Normally in VC++ 7.1 (unmanaged) I would normally just malloc the memory that I needed:

UBYTE *pDataPtr = NULL;
DWORD dwDataSize = 0;

try
{
GetServerSideDataSize(dwDataSize);
pDataPtr = (UBYTE *)malloc(dwDataSize);
if (pDataPtr)
{
GetServerSideData(pDataPtr);
// Do something with pData Now..
free(pDataPtr);
pDataPtr = NULL;
}
}
catch(...)
{
if (pDataPtr)
free(pDataPtr);
}

In my Managed DLL wrapper I've done this so far which fails when I call "new" on the VB.Net side..

namespace CDMSClient_SQL
{
[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRows", CharSet = Ansi)]
STATUS SQLGetRows(const Int32 RowCount, const Int32 DataSize, UBYTE *Data, String *Columns, String *From, String *Where, String *OrderBy);

[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRowInfo", CharSet = Ansi)]
STATUS SQLGetRowInfo(Int32 &RowCount, Int32 &ColumnCount, Int32 &DataSize, String *Columns, String *From, String *Where);
}
Array *CCDMSClientInterface::SQLGetRows(const Int32 MaxRows, String *Columns, String *From, String *Where, String *OrderBy)
{
STATUS Status = EC_OK;
Int32 dwRowCount = 0;
Int32 dwColumnCount = 0;
Int32 dwDataSize = 0;
Array *Data = NULL;
UBYTE __pin *pDataPtr = NULL;

Status = CDMSClient_SQL::SQLGetRowInfo(dwRowCount, dwColumnCount, dwDataSize, Columns, From, Where);
if (Status == EC_OK)
{
pDataPtr = (UBYTE *)new char[dwDataSize]; // <--- This is the line that fails in the Managed VC++ Side
Status = CDMSClient_SQL::SQLGetRows(dwRowCount, dwDataSize, pDataPtr, "*", "CDMS_Config", "", "");
if (Status == EC_OK)
Data = Convert_CDBArray_2_Object(pDataPtr);
}

return (Data);
}

VB.Net Side of code:

Imports ClientInterface = CDMSClientDotNet.CCDMSClientInterface

Module Module1

Sub Main()
Dim ci As ClientInterface = New ClientInterface
Dim Data As Array
Dim Status As Int32

Status = ci.SetApplicationID("43C1F2F1-CB68-4B89-A8C8-5E0C42CE4866")
If Status = 1 Then
Status = ci.SetDomain("Primary")
If Status = 1 Then
Status = ci.CreateServerContext()
If Status = 1 Then
Status = ci.Login("admin", "optical")
If Status = 1 Then
Console.WriteLine("Logged In!")

Data = ci.SQLGetRows(1000, "*", "CDMS_Config", "", "") // <---This is the line that fails in the VB.Net side

ci.Logout()
Else
Console.WriteLine("Failed to Login!")
End If
ci.DeleteServerContext()
Else
Console.WriteLine("Failed to Create Server Context!")
End If
Else
Console.WriteLine("Failed to Set Domain!")
End If
Else
Console.WriteLine("Failed to Set ApplicationID!")
End If
End Sub

End Module
I have many functions that pass data from the server side to the client side via a memory buffer. This data in the memory buffer is parsed and put back into a dynamic array (Custom C++ class called a CDBArray). The first function that I'm trying to get to work, fetches a database table from the server side and marshalls it back over to the client side. The Server and Client is using RPC to marshall data back and forth. (Just a side note, The client side can not access the database directly via ODBC or anything else. It must go thought my client dll. This is done for security reason to keep the client side locked down.)

Any ideas or suggestion are more than welcomed!!

Thanks Again!
Weston Fryatt

Jul 21 '05 #1
2 2269
Weston Fryatt" <wfryatt "at wrote:
In my Managed DLL wrapper I've done this so far which fails when I
call "new" on the VB.Net side.. namespace CDMSClient_SQL
{
[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRows", CharSet =
Ansi)]
STATUS SQLGetRows(const Int32 RowCount, const Int32 DataSize,
UBYTE *Data, String *Columns, String *From, String *Where, String
*OrderBy);

[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRowInfo",
CharSet = Ansi)]
STATUS SQLGetRowInfo(Int32 &RowCount, Int32 &ColumnCount,
Int32 &DataSize, String *Columns, String *From, String *Where);
}
This is managed C++? If so, why are you using platform invoke to access the
methods. Why don't you use an import library (.lib) and use IJW?
Array *CCDMSClientInterface::SQLGetRows(const Int32 MaxRows, String
*Columns, String *From, String *Where, String *OrderBy)
Note that const means nothing to .NET and since you are calling this class
with VB.NET the constness of MaxRows is ignored. What is Array? Is this
System::Array? If so, why are you returning an untyped array?
pDataPtr = (UBYTE *)new char[dwDataSize]; // <--- This is
the line that fails in the Managed VC++ Side
Since you are using unmanaged pointers this should call the unmanaged new.
To make absolutely sure you can write it as

pDataPtr = (UBYTE *)__nogc new char[dwDataSize];

are you sure that this is where the error lies? What is the error message?
have you tried testing dwDataSize to see if it is not zero, and pDataPtr to
see if it is not null?
Status = CDMSClient_SQL::SQLGetRows(dwRowCount, dwDataSize,
pDataPtr, "*", "CDMS_Config", "", "");
if (Status == EC_OK)
Data = Convert_CDBArray_2_Object(pDataPtr);
}
Where do you call delete []?

If SQLGetRows does not care where the memory comes from you can use
Marshal::AllocHGlobal or Marshal::AllocCoTaskMem and then use the
appropriate FreeCoTaskMem and FreeHGlobal. Both of these returns a IntPtr
which can be cast to a void* and then assigned to a pinning pointer.
However, the C++ new should work fine as long as you call delete []
somewhere. (Personally I would bracket the code in try/__finally and call
delete [] in the __finally clause.)

Imports ClientInterface = CDMSClientDotNet.CCDMSClientInterface
This is poor naming, it's a class, not an interface, you cannot call New on
an interface!
Module Module1

Dim Data As Array

Data = ci.SQLGetRows(1000, "*",
"CDMS_Config", "", "") // <---This is the line that fails in the VB.Net
side
Again System.Array is not much use. You should write the managed C++ to
return a typed array instead.
I have many functions that pass data from the server side to the
client side via a memory buffer. This data in the memory buffer is
parsed and put back into a dynamic array (Custom C++ class called a
CDBArray). The first function that I'm trying to get to work,
fetches a database table from the server side and marshalls it back
over to the client side. The Server and Client is using RPC to
marshall data back and forth. (Just a side note, The client side can


RPC should handle any type of memory you pass to it, the RPC layer will
allocate the appropriate buffer. The only time that you'll get a problem is
if you're returning a new array from the RPC method. Are any of the pointers
in SQLGetRows [in,out]?

Richard
--
www.richardgrimes.com
my email ev******@zicf.bet is encrypted with ROT13 (www.rot13.org)
Jul 21 '05 #2
Thanks Richard!

Marshal::AllocHGlobal() did the trick!


"Richard Grimes [MVP]" <read my sig> wrote in message
news:uJ**************@TK2MSFTNGP10.phx.gbl...
Weston Fryatt" <wfryatt "at wrote:
In my Managed DLL wrapper I've done this so far which fails when I
call "new" on the VB.Net side..
namespace CDMSClient_SQL
{
[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRows", CharSet =
Ansi)]
STATUS SQLGetRows(const Int32 RowCount, const Int32 DataSize,
UBYTE *Data, String *Columns, String *From, String *Where, String
*OrderBy);

[DllImport("CDMSClient.dll", EntryPoint = "SQLGetRowInfo",
CharSet = Ansi)]
STATUS SQLGetRowInfo(Int32 &RowCount, Int32 &ColumnCount,
Int32 &DataSize, String *Columns, String *From, String *Where);
}


This is managed C++? If so, why are you using platform invoke to access

the methods. Why don't you use an import library (.lib) and use IJW?
Array *CCDMSClientInterface::SQLGetRows(const Int32 MaxRows, String
*Columns, String *From, String *Where, String *OrderBy)
Note that const means nothing to .NET and since you are calling this class
with VB.NET the constness of MaxRows is ignored. What is Array? Is this
System::Array? If so, why are you returning an untyped array?
pDataPtr = (UBYTE *)new char[dwDataSize]; // <--- This is
the line that fails in the Managed VC++ Side


Since you are using unmanaged pointers this should call the unmanaged new.
To make absolutely sure you can write it as

pDataPtr = (UBYTE *)__nogc new char[dwDataSize];

are you sure that this is where the error lies? What is the error message?
have you tried testing dwDataSize to see if it is not zero, and pDataPtr

to see if it is not null?
Status = CDMSClient_SQL::SQLGetRows(dwRowCount, dwDataSize,
pDataPtr, "*", "CDMS_Config", "", "");
if (Status == EC_OK)
Data = Convert_CDBArray_2_Object(pDataPtr);
}
Where do you call delete []?

If SQLGetRows does not care where the memory comes from you can use
Marshal::AllocHGlobal or Marshal::AllocCoTaskMem and then use the
appropriate FreeCoTaskMem and FreeHGlobal. Both of these returns a IntPtr
which can be cast to a void* and then assigned to a pinning pointer.
However, the C++ new should work fine as long as you call delete []
somewhere. (Personally I would bracket the code in try/__finally and call
delete [] in the __finally clause.)

Imports ClientInterface = CDMSClientDotNet.CCDMSClientInterface


This is poor naming, it's a class, not an interface, you cannot call New

on an interface!
Module Module1

Dim Data As Array

Data = ci.SQLGetRows(1000, "*",
"CDMS_Config", "", "") // <---This is the line that fails in the VB.Net
side
Again System.Array is not much use. You should write the managed C++ to
return a typed array instead.
I have many functions that pass data from the server side to the
client side via a memory buffer. This data in the memory buffer is
parsed and put back into a dynamic array (Custom C++ class called a
CDBArray). The first function that I'm trying to get to work,
fetches a database table from the server side and marshalls it back
over to the client side. The Server and Client is using RPC to
marshall data back and forth. (Just a side note, The client side can


RPC should handle any type of memory you pass to it, the RPC layer will
allocate the appropriate buffer. The only time that you'll get a problem

is if you're returning a new array from the RPC method. Are any of the pointers in SQLGetRows [in,out]?

Richard
--
www.richardgrimes.com
my email ev******@zicf.bet is encrypted with ROT13 (www.rot13.org)

Jul 21 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3232
by: Tom | last post by:
We have a VERY simple .NET C# Form Application, that has about a 23MB Memory Footprint. It starts a window runs a process and does a regular expression. I have done a GC.Collect to make sure that,...
20
4193
by: Philip Carnstam | last post by:
How come .Net applications use so much memory? Every application I compile uses at least 10 MB of memory, even the ones consisting of only a form and nothing else. If I minimize them though the...
0
3883
by: Frank Lopez | last post by:
Does anyone know if Microsoft generated a whitepaper on this topic? Does anyone know what the solution is? (meaning, eliminate the leak problem -- I am seeing three memory leaks from...
4
7164
by: repstat | last post by:
Hi I have a project which is going to be doing some string manipulation which needs to be pretty fast. The user interface is going to be written in C#. I am going to write the string handling...
4
2147
by: | last post by:
I am stuck in a situation and I do believe that this should work, but it doesn't. I have a unmanaged dll, that uses MFC. This works great. Now I recompile the unmanaged dll so it contains...
2
219
by: Weston Fryatt | last post by:
(Sorry for spamming multiple groups, But I need a solution to this problem) I think this should be a simple question on Memory Allocation in a managed DLL and passing a memory pointer over to an...
0
1588
by: Maxwell | last post by:
Hello, I recently completed a MC++ (VS2003) DLL that wraps a non MFC C++ DLL and need to use it in a MC++ Console Application (no forms/guis of any kind just output to console). Trouble is...
9
3100
by: Amit Dedhia | last post by:
Hi All I have a VC++ 2005 MFC application with all classes defined as unmanaged classes. I want to write my application data in xml format. Since ADO.NET has buit in functions available for...
3
4683
by: Klaus | last post by:
Hi, I have an existing VC 6 MFC application which communicates asynchronly with a VC 2005 managed code dll. I use an unmanaged base class with virtual functions to access methods in the MFC...
0
7111
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7376
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7031
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7485
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5042
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4702
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3191
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
1
760
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
412
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.