[Mono-list] InteropServices: DllNotFoundException...?

Jonathan Pryor jonpryor@vt.edu
Sun, 23 May 2004 16:39:32 -0400


On Sun, 2004-05-23 at 11:37, Simon Ask Ulsnes wrote:
> *sigh*
> Hooray for Managed Code! ;-)
> 
> Could you please give a short example of a C++ library function that 
> returns a string for use in a managed application? (with proper memory 
> hygiene ;-)

Sure.  I haven't tried to compile any of this, but it's the right
idea...

	//
	// Unmanaged C++ code
	//

	#include <string>
	#include <stdlib.h>

        /** 
         * To minimize library differences, this function should be used
         * by "external" code (managed code, other 3rd party code) to 
         * free memory allocated within this library.
         *
         * This is particularly important on any platform that has 
         * multiple runtime libraries which each export "free" (say, 
         * Windows, with MSVCRT, GCC, Borland, and lots of other C 
         * runtime library implementations, all of which are 
         * mutually incompatible).
         */
        extern "C" void
        mylib_free (void* mem)
        {
        	free (mem);
        }
        
        /**
         * This is a function which returns a newly allocated string.
         * Callers *must* use mylib_free() to free the returned memory.
         */
        extern "C" char*
        mylib_get_string ()
        {
        	std::string s ("this is my string");
        	// manipulate `s' to fill its contents
        
        	// paranoia: check for integer overflow in buffer size 
        	// calculation.  Consider if s.size() is = 0xFFFFFFFF.
        	// 0xFFFFFFFF + 1 = 0, which is too small to hold the 
        	// required string; any attempt to fill the buffer would
        	// result in memory corruption.
        	// Yes, this is likely absurd, as your app would likely
        	// have crashed by now if it had a string that big, but
        	// better safe than sorry.
        	// For more information, see:
        	// http://msdn.microsoft.com/security/securecode/columns/default.aspx?pull=/library/en-us/dncode/html/secure04102003.asp 
        	std::string::size_type size = s.size();
        	if (size + 1 <= size) return NULL;
        	size += 1;
        
        	// return newly allocated string.
        	char *r = (char*) malloc (size);
        	if (!r) return NULL;
        	strcpy (r, s.c_str());
        	return r;
        }
        
        //
        // Managed code
        //
        
        using System;
        using System.Runtime.InteropServices;
        
        class Mylib {
        	[DllImport ("mylib")]
        	private static extern void mylib_free (IntPtr r);
        
        	[DllImport ("mylib")]
        	private static extern IntPtr mylib_get_string ();
        
        	public static string GetString ()
        	{
        		IntPtr r = mylib_get_string ();
        		if (r == IntPtr.Zero) return null;
        		string s = null;
        		try {
        			s = Marshal.PtrToStringAnsi (r);
        		}
        		finally {
        			mylib_free (r);
        		}
        		return s;
        	}
        }

 - Jon