Click here to Skip to main content
Click here to Skip to main content

Simple Method of DLL Export without C++/CLI

By , 27 Jun 2009
 
Sample output

Introduction

In .NET, you can make managed and unmanaged code work together. To call an unmanaged function from managed code, you can use Platform Invoke technology (shortly P/Invoke). P/Invoke is available in all managed languages. Using P/Invoke is as simple as defining correct method signature and adding a DllImport attribute to it. Usually it seems like this:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

But when you need to call a managed function from unmanaged code, a common way to do it is to write a wrapper — separate mixed mode DLL implemented in C++/CLI (formerly Managed Extensions for C++) that exports unmanaged functions and can access managed classes, or implement whole class library in C++/CLI. This is an advanced task and requires knowledge of both managed languages and C++. I was wondering why there is no DllExport attribute that will allow to expose flat API from any managed language.

Inside .NET Assembly

Code written in managed language is compiled into bytecode — commands for .NET virtual machine. This bytecode can be easily disassembled into MSIL (Microsoft Intermediate Language) which looks similar to machine assembly language. You can view IL code using ildasm.exe included in .NET SDK or Reflector tool. This simple class:

namespace DummyLibrary
{
    public class DummyClass
    {
        public static void DummyMethod() { }
    }
}

after compiling and disassembling gives this code:

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
  .ver 2:0:0:0
}
.assembly DummyLibrary
{
  // Assembly attributes…
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module DummyLibrary.dll
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY

// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi beforefieldinit DummyLibrary.DummyClass
       extends [mscorlib]System.Object
{
  .method private hidebysig static void 
          DummyMethod() cil managed
  {
    .custom instance void [DllExporter]DllExporter.DllExportAttribute::.ctor() = 
							( 01 00 00 00 ) 
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ret
  } // end of method DummyClass::DummyMethod

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method DummyClass::.ctor
} // end of class DummyLibrary.DummyClass

A very simple wrapper for the above class:

#include "stdafx.h"

void __stdcall DummyMethod(void)
{
	DummyLibrary::DummyClass::DummyMethod();
}
LIBRARY	"Wrapper"
EXPORTS
	DummyMethod

after compiling and disassembling gives lots of IL code, but in short it will look like this:

// Referenced assemblies…
.assembly Wrapper
{
  // Assembly attributes…
  .hash algorithm 0x00008004
  .ver 1:0:3466:3451
}
.module Wrapper.dll
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0002       // WINDOWS_GUI
.corflags 0x00000010    // 
.vtfixup [1] int32 retainappdomain at D_0000A000 // 06000001
// Other .vtfixup entries…

// C++/CLI implementation details…

.method assembly static void modopt
	([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) 
        DummyMethod() cil managed
{
  .vtentry 1 : 1
  .export [1] as DummyMethod
  .maxstack  0
  IL_0000:  call       void [DummyLibrary]DummyLibrary.DummyClass::DummyMethod()
  IL_0005:  ret
} // end of global method DummyMethod

.data D_0000A000 = bytearray (
                 01 00 00 06) 

// Raw data…

The important differences between these two IL listings are:

  1. .corflags keyword which tells Windows how to load the assembly
  2. .vtfixup keyword which adds an empty slot to assembly VTable
  3. .data keyword which reserves memory to store RVA (Relative Virtual Address) for corresponding VTable entry
  4. .vtentry keyword which assigns method with VTable entry
  5. .export keyword which adds method into export table and assigns an entry point name to it.

If you add these keywords to first IL listing properly and assemble it with ilasm.exe, you will get an assembly that exports unmanaged APIs without using mixed-mode wrapper. Final IL code will look like:

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 
  .ver 2:0:0:0
}
.assembly DummyLibrary
{
  // Assembly attributes…
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module DummyLibrary.dll
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000002    //  32BITSREQUIRED
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)

// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi beforefieldinit DummyLibrary.DummyClass
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  DummyMethod() cil managed
  {
    .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor() = ( 01 00 00 00 ) 
    .custom instance void 
    .vtentry 1 : 1
    .export [1] as DummyMethod
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ret
  } // end of method DummyClass::DummyMethod

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method DummyClass::.ctor

} // end of class DummyLibrary.DummyClass

When the resulting DLL is loaded by unmanaged executable, CLR will be initialized and will replace reserved RVA entries with actual addresses. Exported function calls will be intercepted by CLR and corresponding managed code will be executed.

DllExporter

Obviously editing IL code manually after each change is irrational. So I decided to write a utility that will perform these actions automatically after each build. To mark which methods will be exported, you need to add reference to DllExporter.exe to your project and add DllExporter.DllExport attribute to selected static methods. Instance methods cannot be exported. After build, you can run DllExporter.exe <path to assembly> and program will disassemble the given assembly, create VTFixup entries, replace DllExport attributes with references to corresponding VTable entries and removes DllExporter.exe assembly reference. Resulting assembly will be saved into AssemblyName.Exports.dll. You do not need DllExporter.exe to use the resulting assembly. Resulting assembly will be 32-bit only. To run DllExporter after each build, you can go to Visual Studio -> Project Properties -> Build Events and add the following post-build commands:

DllExporter.exe $(TargetFileName)
move $(TargetName).Exports$(TargetExt) $(TargetFileName)

Examples

You can mark any static method with [DllExport]. Method does not need to be public. Instance methods marked with [DllExport] will be ignored. Now define class DummyClass with some methods:

[DllExport]
public static void DummyMethod() { }

DummyMethod will be available as DummyMethod static entry point.

[DllExport(EntryPoint = "SayHello")]
[return:MarshalAs(UnmanagedType.LPTStr)]
public static string Hello([MarshalAs(UnmanagedType.LPTStr)]string name)
{
    return string.Format("Hello from .NET assembly, {0}!", name);
}

You can use EntryPoint property to define entry point name different to method name. Complex types like strings and arrays should be correctly marshaled to unmanaged code using MarshalAs attribute. To use your managed DLL from unmanaged application, you should get function pointer with LoadLibrary and GetProcAddress like for any other DLL:

typedef LPTSTR (__stdcall *HelloFunc)(LPTSTR name);

// ...

HMODULE hDll = LoadLibrary(L"DummyLibrary.dll");
if (!hDll)
	return GetLastError();

HelloFunc helloFunc = (HelloFunc)GetProcAddress(hDll, "SayHello");
if (!helloFunc)
	return GetLastError();
wprintf(L"%s\n", helloFunc(L"unmanaged code"));

Unmanaged C++ does not know about .NET types but .NET strings are transparently marshaled from and to plain zero-terminated strings. To use arrays, you must specify through MarshalAs attribute how to get array length:

[DllExport]
public static int Add([MarshalAs
	(UnmanagedType.LPArray, SizeParamIndex = 1)]int[] values, int count)
{
    int result = 0;

    for (int i = 0; i < values.Length; i++)
        result += values[i];

    return result;
}
typedef int (__stdcall *AddFunc)(int values[], int count);

AddFunc addFunc = (AddFunc)GetProcAddress(hDll, "Add");
if (!addFunc)
	return GetLastError();
int values[] = {1, 2, 3, 4, 5 };
wprintf(L"Sum of integers from 1 to 5 is: %d\n", 
		addFunc(values, sizeof(values) / sizeof(int)));
You can pass structures by value, pointer or reference:
[StructLayout(LayoutKind.Sequential)]
public struct DummyStruct
{
    public short a;
    public ulong b;
    public byte c;
    public double d;
}
[DllExport]
public static DummyStruct TestStruct() 
	{ return new DummyStruct { a = 1, b = 2, c = 3, d = 4 }; }

[DllExport]
public static void TestStructRef(ref DummyStruct dummyStruct)
{
    dummyStruct.a += 5;
    dummyStruct.b += 6;
    dummyStruct.c += 7;
    dummyStruct.d += 8;
}
struct DummyStruct
{
	short a;
	DWORD64 b;
	byte c;
	double d;
};

typedef DummyStruct (__stdcall *StructFunc)(void);
typedef void (__stdcall *StructRefFunc)(DummyStruct& dummyStruct);
typedef void (__stdcall *StructPtrFunc)(DummyStruct* dummyStruct);
StructFunc structFunc = (StructFunc)GetProcAddress(hDll, "TestStruct");

if (!structFunc)
	return GetLastError();
DummyStruct dummyStruct = structFunc();
wprintf(L"Struct fields are: %d, %llu, %hhu, %g\n", 
	dummyStruct.a, dummyStruct.b, dummyStruct.c, dummyStruct.d);

StructRefFunc structRefFunc = (StructRefFunc)GetProcAddress(hDll, "TestStructRef");
if (!structRefFunc)
	return GetLastError();
structRefFunc(dummyStruct);
wprintf(L"Another struct fields are: %d, %llu, %hhu, %g\n", 
	dummyStruct.a, dummyStruct.b, dummyStruct.c, dummyStruct.d);

StructPtrFunc structPtrFunc = (StructPtrFunc)GetProcAddress(hDll, "TestStructRef");
if (!structPtrFunc)
	return GetLastError();
structPtrFunc(&dummyStruct);
wprintf(L"Yet another struct fields are: %d, %llu, %hhu, %g\n", 
	dummyStruct.a, dummyStruct.b, dummyStruct.c, dummyStruct.d);

Finally, you can exchange unmanaged code with delegates:

public delegate void Callback([MarshalAs(UnmanagedType.LPTStr)]string name);

[DllExport]
public static void DoCallback(Callback callback)
{
    if (callback != null)
        callback(".NET assembly");
}
typedef void (__stdcall *CallbackFunc)(Callback callback);

void __stdcall MyCallback(LPTSTR name)
{
	wprintf(L"Hello from unmanaged code, %s!\n", name);
}

CallbackFunc callbackFunc = (CallbackFunc)GetProcAddress(hDll, "DoCallback");
if (!callbackFunc)
	return GetLastError();
callbackFunc(&MyCallback);

For more complex cases, like working with unmanaged classes you still need to use C++/CLI, but using only managed language you still can create extensions for unmanaged applications, for example, plugins for Total Commander and vice versa.

Using Assembly with Managed Code

If you are running 64-bit OS and try to use assembly with exports in another managed application, you probably get BadImageFormat exception because assembly is 32-bit and .NET applications by default are running in 64-bit mode. In this case, you should make your application 32-bit: Visual Studio -> Project Properties -> Build -> Platform Target -> x86. You can use assembly with exports directly or through P/Invoke — the result will be the same:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DummyLibrary.DummyClass.Hello(".NET application"));
        Console.WriteLine(SayHello(".NET application"));
    }

    [DllImport("DummyLibrary.dll", CharSet = CharSet.Unicode)]
    public static extern string SayHello(string name);
}

Information Sources

Some information was taken from the article Exporting Managed code as Unmanaged by Jim Teeuwen.

History

  • 28th June, 2009: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Dark Daskin
Russian Federation Russian Federation
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionarray to unmanagedmemberMember 38516803 Mar '13 - 21:35 
please tell me how to pass an array from managed to unmanaged code?
QuestionPassing parameters by referencememberJimmyRopes1 Mar '13 - 4:02 
Is there a way to pass parameters from unmanaged code to managed code by reference?

The report of my death was an exaggeration - Mark Twain

Simply Elegant Designs JimmyRopes Designs
Think inside the box! ProActive Secure Systems

I'm on-line therefore I am.
JimmyRopes


QuestionUsing on WindowsCe ClassesmemberKitro1 Aug '12 - 4:03 
Hi
I tried to use this with my Windows Ce DLL File but it didn't work.
Are there need to change anything to get it work with WindowsCe?
.
.
.
[DllExporter.DllExport]
[return: MarshalAs(UnmanagedType.SysInt)]
public static int test([MarshalAs(UnmanagedType.LPTStr)]string name, [MarshalAs(UnmanagedType.LPTStr)]out string result)
        {
            result = name.ToUpper() + " done";
            return 0;
        }
.
.
.

Questioncanot be loaded in Delphi projectmemberww2010092928 Nov '11 - 14:49 
Dear author
   I downloaded your source code and compiled succeed. But when I use your SayHello function of the DummyLibrary dll in my delphi project, it threw exception. It is ok that call this function in VS console appliction referenced the DummyLibrary dll. Can you help me? thank you!
 
Delphi SourceCode:
 
TGetString = function(name:string):string;stdcall;
var
   dllHandle:THandle;
   fun:TGetString;
   aword:string;
begin
   dllHandle := LoadLibrary('C:\DummyLibrary.dll');
   try
      @fun : = GetProcAddress(dllHandle,'SayHello');
      if Assigned(@fun) then
      begin
         aword:=fun('hello');
      end;
   finally
      freelibrary(dllHandle);
   end;
end;
AnswerRe: canot be loaded in Delphi projectmemberViRuSTriNiTy25 Aug '12 - 22:07 
Hi,
 
i think this does not work because the Delphi "String" is not zero terminated, its actually a Delphi specific type. Using Delphi strings in connection with DLLs also require the use of Borland memory manager. So you cannot use it here. Try to use PChar instead.
 
Btw i also think the SayHello example introduces a memory leak / possible access violation because it returns a pointer from a DLL whereas the memory behind the pointer should be freed inside the DLL not outside the DLL.
QuestionRe: Call using VB6membermla15415 Jul '11 - 7:22 
Hello,
I appreciate the work you put into this.  I was able to call the managed DLL from C++ using the code you suggested:
typedef LPTSTR (__stdcall *HelloFunc)(LPTSTR name);
 
// ...

HMODULE hDll = LoadLibrary(L"DummyLibrary.dll");
if (!hDll)
	return GetLastError();
 
HelloFunc helloFunc = (HelloFunc)GetProcAddress(hDll, "SayHello");
if (!helloFunc)
	return GetLastError();
wprintf(L"%s\n", helloFunc(L"unmanaged code"));
How do I make this call using VB6?
Regards,
Mike

GeneralDebugger does not hit on breakpointsmemberNavinBiz11 Feb '11 - 20:18 
Anyone managed to make debugger work with .dll's patched this way? It doesn't hit breakpoints.
GeneralRe: Debugger does not hit on breakpoints [modified]memberdmihailescu14 Jul '11 - 5:19 
I have not tried this solution but a similar one described at here, allows for debugging using VS2010.
I've tested myself the unmanaged C++ to managed code call and the debugger worked for an x86 assembly. Make sure you set the starting program under the debugging options appropriately in the project properties.
If you have the source code of the caller, you can also try setting the debug mode to 'Mixed' and debug both the caller and this dll. That worked for me too.

modified 22 Oct '11 - 9:55.

QuestionAfter doing an export of my classmemberMember 470178810 Oct '10 - 22:57 
I have tryed to do an export of my class but can not seem to get it to work
My code for the export looks like this in the il DASM
Method #2 (06000010) 
	-------------------------------------------------------
		MethodName: GetName (06000010)
		Flags     : [Public] [Static] [HideBySig] [ReuseSlot]  (00000096)
		RVA       : 0x00003ab0
		ImplFlags : [IL] [Managed]  (00000000)
		CallCnvntn: [DEFAULT]
		ReturnType: String
		No arguments.
		1 Parameters
			(0) ParamToken : (0800000d) Name :  flags: [HasFieldMarshal]  (00002000)
				NATIVE_TYPE_LPSTR 
		CustomAttribute #1 (0c000015)
		-------------------------------------------------------
			CustomAttribute Type: 0600001e
			CustomAttributeName: DllExporter.DllExportAttribute :: instance void .ctor()
			Length: 25
			Value : 01 00 01 00 54 0e 0a 45  6e 74 72 79 50 6f 69 6e >    T  EntryPoin<
                              : 74 07 47 65 74 4e 61 6d  65                      >t GetName       <
			ctor args: ()
 
My Export in the class looks like this.
 
/// <summary>
        /// GetName
        /// </summary>
        /// <returns>Name of the assembly</returns>
        [DllExport(EntryPoint = "GetName")]
        [return:MarshalAs(UnmanagedType.LPStr)]
        public static string GetName()
        {
            Module[] moduleArray;
            string[] Split;
            moduleArray = Assembly.GetExecutingAssembly().GetModules(true);
            Module MyModule = moduleArray[0];
            Split = MyModule.Assembly.FullName.Split(',');
            return Split[0];
        }
 
Could some one tell me what is wrong ????
if it was not for the fact that i was blond i would be greay by now Smile | :)
GeneralBetter solution!!membergorallo27 Aug '10 - 22:13 
http://sites.google.com/site/robertgiesecke/
GeneralRe: Better solution!!memberdmihailescu14 Jul '11 - 5:11 
That's indeed very conveniently integrated with VS, but I can't find its source code.
GeneralRe: Better solution!!membergorallo16 Jul '11 - 2:03 
ilspy, reflector, dotpeek Smile | :)
GeneralMy vote of 1memberSelvin9 Jul '10 - 2:59 
Unmanaged code can wrap managed methods[^]
 
How to Automate Exporting .NET Function to Unmanaged Programs[^]
 
any way:
 
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)
 
is outdated
QuestionWhat about pass by reference of string array?memberAriston Darmayuda24 Jun '10 - 18:10 
I want to export function like this:
 
public static void CreateArray(ref string[] arrayOut)
{
  arrayOut = new string[]{"Hello","World"};
}

GeneralIs this different from the 2006 article at http://www.codeproject.com/KB/dotnet/DllExport.aspxmemberpietje puk22 Jun '10 - 22:41 
The following article (from 2006!) already describes the same steps (including 64bit support). Take your pick.
 
How to Automate Exporting .NET Function to Unmanaged Programs[^]
QuestionProblem with Delphi :pchar and stringsmemberDaniel Aguerrevere28 Mar '10 - 15:29 
Hello, thanks for the DllExporter, it is great and easy to use. I'm trying to create this DLL that will get called from a Delphi program. In order to interface the unmanaged Delphi program with the managed C#, I'm trying to make an intermediary bridge DLL. So far I've been able to make it accessible to the Delphi program, but I'm having problems returning a string which is passed as a pchar parameter.
 
Delphi signature for the function I'm implementing:
function ElectronicPay(const input :pchar, var output :pchar):boolean; export; stdcall;
 
C# bridge implementation so far:
        [DllExport]
        public unsafe static bool ElectronicPay(string input, IntPtr output)
        {
            string managedOutput = Marshal.PtrToStringAnsi(output);
 
            Terminal.ElectronicPay(input, ref managedOutput);
 
            output = Marshal.StringToHGlobalAnsi(managedOutput);
            return true;
        }
 
Now the input string works perfectly. However I'm having problems with producing the output. I'm pretty sure I'm not supposed to allocate the memory for output, but rather use what they should have given me already preallocated. However I haven't been able to get the string they are sending in in the output parameter. Can anybody shine some light on how to deal with this situation. Please note that I don't have any control nor source code of the Delphi program.
 
Thanks.
Dan
GeneralNice JobmemberDigvijay Chauhan10 Feb '10 - 3:13 
Hi,
 
Thanks for sharing. This is a nice and easy to use tool. Thumbs Up | :thumbsup:
 
regards,
 
Digvijay
Regards,
 
Digvijay

QuestionWhat does it take to make this available from a 64 bit unmanaged application running .NET in 64 bit. [modified]memberRuben_uniek10 Nov '09 - 9:46 
Hi,
 
Any suggestion how this could be used for 64 bit application development?
 
Many Thanks,
 
Ruben Nijp
 
Contractor
Vita Solutions
 
modified on Tuesday, November 10, 2009 4:11 PM

AnswerRe: What does it take to make this available from a 64 bit unmanaged application running .NET in 64 bit.memberRuben_uniek10 Nov '09 - 10:01 
Just figured it out....
 
32 bit assemblies need there IL code being updated to:
 
.corflags 0x00000002
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32[1]
 
where 64 bit assemblies must be updated to:
 
.corflags 0x00000008
.vtfixup [1] int64 fromunmanaged at VT_01
.data VT_01 = int64[1]
 

Thus, the following changes need to be made in order to do 64 bit assemblies
 
1) At ProcessSource()
 
if (line.TrimStart(' ').StartsWith(".corflags"))
{
output.WriteLine(".corflags 0x00000008");
 
for (int i = 1; i <= methods.Count; i++)
output.WriteLine(".vtfixup [1] int64 fromunmanaged at VT_{0}", i);
 
for (int i = 1; i <= methods.Count; i++)
output.WriteLine(".data VT_{0} = int64(0)", i);
 
continue;
}
 

2) At Assemble()
 
// Dont forget the x64 flag
args.AppendFormat(@"""{0}\output.il"" /pdb /x64 /out:""{1}""", workDir, outPath);
GeneralProblem: Calling conventionmemberSteven12345678907 Oct '09 - 12:51 
I am trying out your code but I ran into the following problem:
 
The calling convention defaults to stdcall, but the C calls into my managed DLL needs to use the cdecl convention (I can't change this). How can I fix this? Ideally another property should be added to the DllExport attribute that defines the calling convention, and the IL generator should then create the correct output in this case.
 
Any ideas?
QuestionDoes COM work?memberSteven12345678906 Oct '09 - 19:44 
Very nice!
 
So I am interested in using your way of eliminating the intermediate managed C++ DLL. But I am currently experiencing a problem in my code with Drag & Drop because in my project, COM is not initialized properly (I think this is the root problem). I am trying to solve this, but I am wondering if you are aware whether things like Drag & Drop is fully supported if I use your mechanism instead.
 
Thanks!
GeneralGreat!memberdimzon20 Jul '09 - 5:56 
Действительно прикольно Wink | ;)
Может быть полезно когда хочется быстро прикрутить какое-нить говнецо к существующему unmanaged-проекту
QuestionUsage of var and other code... [modified]memberMember 245509414 Jul '09 - 21:31 
I find the article very informative, with good examples too.
 
I am using VS 2005 with .Net 2.0 framework, I dont have VS 2008 and presently want to continue with current framework and VS version only.
 
I have few questions/ remarks:
 
1) Why you used var type, which ofcourse is a feature of .Net 3.0 framework and above when you could have used available types with framework.
 
2) In ProcessSource method in DllExporter project, why have you used the block...
 
foreach (var ch in line)
{
if (ch == '(')
openBraces++;
if (ch == ')')
openBraces--;
}
 
2 times. I dont see its use in processing and giving final results. whats its actual purpose, should it be removed?
 
3) In class DllExportAttribute you have left implementation of get and set methods empty, we need to store the value of entrypoint so that later it can be retrieved.
 
4) how can I debug post build of .NET code during the running of UnManaged Code. Its not allowing me giving error message "the following module was built either with optimizations enabled or without debug information", when all my project setting are corrent including debug mode and output settings. I guess its because the dll has been modified with our dllexporter.exe utility but not the corresponding .pdb file. Any way it can be debugged, may be by modifying .pdb file?
 
5) How should we use marshalling in exported functions in .NET if VC++ code is expecting LPCTSTR, because in MarshalAs enumertaion only LPTStr exists?
 
Your early and descriptive reply would be very helpful.
 
thanks,
Nikhil.
 
modified on Wednesday, July 22, 2009 2:57 AM

QuestionРегрессия?memberMember 30824871 Jul '09 - 23:41 
Как реализация моста "в обратную сторону" - превосходно, но по идее прогресса мы наоборот, идём к Дотнету, попутно волоча непереписываемые unmanaged библиотеки.
Да и нет смысла "нативным" приложениям иметь "гири" в виде дотнета, проще подключить библиотечку.
Кстати, а вы сами как эту технику используете?
AnswerRe: Регрессия?memberACNZdev7 Sep '09 - 17:16 
Снимаю шляпу перед Dark Daskin!
Это технология как раз и есть огромный шаг в направлении .NET. Мой текущий прект требует написания плагинов в формате DLL для сервера железа. Эти плагины обеспечивают HMI и интеграцию с остальной ситемой, написанной в .NET.
Dark Daskin только что освободил меня от писанины "нативного" кода который не делает ничего кроме интерфейса с .NET which rules, by the way.
Не знаю как выразить благодарность.
Всего хорошего!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 28 Jun 2009
Article Copyright 2009 by Dark Daskin
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid