Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / May 2006

Tip: Looking for answers? Try searching our database.

Memory allocation in C# callback

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
mortb - 27 Apr 2006 09:41 GMT
Hi!

I'm writing a C# program that uses a dll-library called libmng.
The library relies heavily on callback fucntions.
To use it you have to provide callbacks for memory allocation ammongst other
things.
Using Marshal.AllocHGlobal memroy allocation seems to work ok, but I get
wierd errors that my memory free delegate gets called without actually
beeing called in the library. I've written some C# and C code to test my
callbacks:

C#:
--------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace liteTest
{
   public unsafe class MyTest
   {
       private const string DLLPATH = @"..\..\..\testDll\Debug\testDll";

       [DllImport(DLLPATH)]
       private static extern IntPtr initialize(IntPtr userData,
memoryAllocDelegate memoryAllocationCallback, memoryFreeDelegate
memoryDeAllocationCallback);

       private delegate IntPtr memoryAllocDelegate(int size);

       private memoryAllocDelegate _memoryAllocationCallback;

       private delegate void memoryFreeDelegate([In, Out] IntPtr
memoryToFree, uint size);

       private memoryFreeDelegate _memoryFreeCallback;

       public MyTest()
       {
       }

       public void init()
       {
           _memoryAllocationCallback = new memoryAllocDelegate(myAlloc);
           _memoryFreeCallback = new memoryFreeDelegate(myFree);

           initialize(IntPtr.Zero, _memoryAllocationCallback,
_memoryFreeCallback);
       }

       private int _numberOfCallsToAlloc = 0;

       private IntPtr myAlloc(int size)
       {
           IntPtr chunkOfMemory = Marshal.AllocHGlobal(size);
           Console.WriteLine("{0} C# Alloc:{1},{2}",
++_numberOfCallsToAlloc, chunkOfMemory, size);
           return chunkOfMemory;
       }

       private void myFree(IntPtr ptrToMemory, int size)
       {
           Console.WriteLine("C# Free:{0}", ptrToMemory);
           Marshal.FreeHGlobal(ptrToMemory);
       }
   }

   class console
   {
       static void Main(string[] args)
       {
           MyTest test = new MyTest();
           test.init();
           Console.ReadKey();
       }
   }
}

--------------------------------------------------------

C:
--------------------------------------------------------
#include <stdio.h>
#include <windows.h>

extern "C" __declspec(dllexport)
void * initialize
(void * userData,
void * (*memoryAllocationCallback)(int size),
void (*memoryDeAllocationCallback)(void * ptr, int size))
{
   int i, j;
   int sizeToAlloc = 8;
   void * tmp_ptr;
   printf("Hello from DLL!\n");

   for(i = 0; i < 10; i++)
   {
       tmp_ptr = memoryAllocationCallback(sizeToAlloc );
       printf("C++ pointer adress: %d\n", tmp_ptr);
   }
   return NULL;
}
----------------------------------------------------------
This is the output when runniig the DLL in the debugger:

Hello from DLL!
1 C# Alloc:1830872,8
C++ pointer adress: 1830872
2 C# Alloc:1830888,8
C++ pointer adress: 1830888
3 C# Alloc:1844336,8
C++ pointer adress: 1844336
4 C# Alloc:1847112,8
C++ pointer adress: 1847112
5 C# Alloc:1848584,8
C++ pointer adress: 1848584
6 C# Alloc:1848600,8
C++ pointer adress: 1848600
7 C# Alloc:1848616,8
C++ pointer adress: 1848616
8 C# Alloc:1848632,8
C++ pointer adress: 1848632
9 C# Alloc:1848648,8
C++ pointer adress: 1848648
10 C# Alloc:1848664,8
C++ pointer adress: 1848664
C# Free:2045708296

The memory allocation seems to work -- the pointers seem to be the same in
C# and C.
However, last in the output is a weird call to my memory free callback,
which I haven't put in my code with some adress that has never been
allocated. My questions are: Why is the free callback called when not
programmed to do so? This is the first time I do anything like this and I'm
not that good at C or interop, am I doing something totally wrong here?

*Any* help appreciated!
cheers,
mortb
Christian Fröschlin - 27 Apr 2006 11:18 GMT
> allocated. My questions are: Why is the free callback called when not
> programmed to do so? This is the first time I do anything like this and I'm
> not that good at C or interop, am I doing something totally wrong here?

The code looks reasonable to me. Try setting a breakpoint
in the free delegate and have a look at the call stack.
mortb - 27 Apr 2006 12:33 GMT
According to the stack trace the call to myFree was from the initialize
method which is defined in my C dll.
But the callback myFree is never called, it is just passed as a parameter
into the initialize C method.

  at
System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32
errorCode, IntPtr errorInfo)
  at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32
errorCode)
  at System.Runtime.InteropServices.Marshal.FreeHGlobal(IntPtr hglobal)
  at liteTest.MyTest.myFree(IntPtr ptrToMemory, Int32 size) in
C:\\Projects\\liteTest\\Program.cs:line 57
  at liteTest.MyTest.initialize(IntPtr userData, memoryAllocDelegate
memoryAllocationCallback, memoryFreeDelegate memoryDeAllocationCallback)
  at liteTest.MyTest.init() in C:\\Projects\\liteTest\\Program.cs:line 34
  at liteTest.console.Main(String[] args) in
C:\\Projects\\liteTest\\Program.cs:line 66

cheers,ortb

>> allocated. My questions are: Why is the free callback called when not
>> programmed to do so? This is the first time I do anything like this and
[quoted text clipped - 3 lines]
> The code looks reasonable to me. Try setting a breakpoint
> in the free delegate and have a look at the call stack.
Christian Fröschlin - 27 Apr 2006 13:01 GMT
> According to the stack trace the call to myFree was from the initialize
> method which is defined in my C dll.
> But the callback myFree is never called, it is just passed as a parameter
> into the initialize C method.

There may be some problem on the stack, so that the return statement
of "initialize" actually jumps to the free method (the address of
which has been conveniently pushed on the stack neighborhood).

I'm a bit hazy on old C's pointerisms, but is

void (*memoryDeAllocationCallback)(void * ptr, int size)

really correct? Maybe it should be "void * (something)".
mortb - 27 Apr 2006 13:29 GMT
Well I am way beyond my skills in C/C++, so I corrected my method signature
according to your suggestions.
But that does not help the error, unforturnately.

/Mortb

>> According to the stack trace the call to myFree was from the initialize
>> method which is defined in my C dll.
[quoted text clipped - 10 lines]
>
> really correct? Maybe it should be "void * (something)".
"Peter Huang" [MSFT] - 28 Apr 2006 09:11 GMT
Hi Mortb,

Based on my test, I can not reproduce the problem.
Also I will get many CallingConvention error.
Here is my revised version which works OK at my side, it will not call the
dealloc callback.

["C#"]
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace TestCPPDllCallBackFunc
{
   public unsafe class MyTest
   {
       private const string DLLPATH = @"DLLPath";

       [DllImport(DLLPATH,CallingConvention=CallingConvention.StdCall)]
       private static extern IntPtr initialize(IntPtr
userData,memoryAllocDelegate memoryAllocationCallback, memoryFreeDelegate
memoryDeAllocationCallback);

       private delegate IntPtr memoryAllocDelegate(int size);

       private memoryAllocDelegate _memoryAllocationCallback;
       
       private delegate void memoryFreeDelegate([In, Out] IntPtr
memoryToFree, int size);

       private memoryFreeDelegate _memoryFreeCallback;

       public MyTest()
       {
       }

       public void init()
       {
           _memoryAllocationCallback = new memoryAllocDelegate(myAlloc);
           _memoryFreeCallback = new memoryFreeDelegate(myFree);

           initialize(IntPtr.Zero,
_memoryAllocationCallback,_memoryFreeCallback);
       }

       private int _numberOfCallsToAlloc = 0;

       private IntPtr myAlloc(int size)
       {
           IntPtr chunkOfMemory = Marshal.AllocHGlobal(size);
           Console.WriteLine("{0} C#
Alloc:{1},{2}",++_numberOfCallsToAlloc, chunkOfMemory, size);
           return chunkOfMemory;
       }

       private void myFree(IntPtr ptrToMemory, int size)
       {
           Console.WriteLine("C# Free:{0}", ptrToMemory);
           Marshal.FreeHGlobal(ptrToMemory);
       }
   }

   class Program
   {
       static void Main(string[] args)
       {
           MyTest test = new MyTest();
           test.init();
           Console.ReadKey();
       }
   }
}

[C++]
extern "C" __declspec(dllexport)
void * initialize
(void * userData,
void * (__stdcall *  memoryAllocationCallback)(int size),
void (__stdcall *  memoryDeAllocationCallback)(void * ptr, int size))
{
   int i, j;
   int sizeToAlloc = 8;
   void * tmp_ptr;
   printf("Hello from DLL!\n");

   for(i = 0; i < 10; i++)
   {
       tmp_ptr = memoryAllocationCallback(sizeToAlloc );
       printf("C++ pointer adress: %d\n", tmp_ptr);
   }
   return NULL;
}

You may have a try and let me know the result.

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
mortb - 02 May 2006 12:00 GMT
Thank you!

The stdcall bit seems to have solved the issue!

cheers,
mortb

> Hi Mortb,
>
[quoted text clipped - 104 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Peter Huang" [MSFT] - 03 May 2006 04:02 GMT
Hi

You are welcomed!

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.