Compact 2013 Ebook

17.5 C# P/Invoke
Created by djones on 6/28/2013 8:02:24 AM

Calling Native Code from C# Managed Code

In this activity, the C# project from 17.3 will be modified so as to again call the TimDLL.dll as developed in the Native Code chapter to get the local time.

A Summary of what is required

  • A Compact 2013 C++ Native DLL (that builds to “TimeDLL.dll” ):

    • In the Header file (Note prepending of extern "C" )
      extern "C" TIMEDLL_API  void GetTime( TCHAR * timeStr);    
    • In the source file:
      extern "C" TIMEDLL_API  void GetTime(TCHAR * timeStr)
      
      { 
      
              //The code as previous for getting the Local Time and creating formatted string 
      
      }

  • A Compact 2013 C# Windows Form application
    • Create an internal static class  PInvoke
       
      Provide native function signature:
  •                 [DllImport( “TimeDLL.dll” )] 
    
                    public static extern void GetTime( StringBuilder timeStr);
    
    • In the the form where required
  •               StringBuilder timeStr = new StringBuilder(..); 
    
                  PInvoke.GetTime(timeStr);
    • Need using using references:  using System.Runtime.InteropServices in PInvoke class code.

Implementation

  1. The DLL: Complete Exercise 14.8 to create the TimeDLL.dll as part of the OS project, if you haven't already.

    Note, For this exercise to work, the DLL must be in the \Windows directory (  or the in the build release directory on the OS development system). By building the DLL as an OS subproject, that requirement is effected. If the DLL was was created as an SDK project then that would not be the case and it would need to be moved to \Windows. Alternatively the DLL could be referred to in the signature with a path, but remember there is no such thing as a relative path in Windows Embedded Compact/CE so it would need to be an absolute path.
  2. The App : Complete Exercise 17.2 to create the non-P/Invoked version of the app to get the local time in a second instance of Visual Studio, if you haven't already.

    Next add a class which will encapsulate the native code in the C# application:
  3. Add a class to the application, call it P/Invoke
    App project context (Right-click on the app in Solution Explorer)—>Add Class
    Code it as follows:

    using System; 
    
    using System.Text; 
    
    using System.Runtime.InteropServices; 
    
    namespace ManagedTime 
    
    { 
    
        internal static class PInvoke 
    
        {
    
        } 
    
    } 
    


    Note: The System.Text reference is for the StringBuilder class. Whilst C strings can be passed by value to native code, to marshal a string that needs to be returned from native code it needs to be a StringBuilder object. This object will be initialized with a certain capacity and passed by reference to the native code which then embellishes it with the formatted local time string. That way memory management is handled by the managed code. The native code could have generated space for it on the heap but this would have lead to a memory leak.

  4. Add the following to the PInvoke class:

                    [DllImport( “TimeDLL.dll” )] 
    
                    public static extern void GetTime( StringBuilder timeStr);
    

  5. Add the following reference at the top of the app code:

    using System.Text;
  6. Modify the TimeButton event handler to:

    //Create a StringBuilder object with capacity for 100 characters 
    
    StringBuilder timeStr = new StringBuilder(100);
    
    //Call the native code 
    
    PInvoke.GetTime(timeStr);
    
    //Display the string 
    
    textBox1.Text = timeStr.ToString( );
    
  7. Build and test run the application.

    A runtime error will be reported that the GetTime entry point couldn't be found in the DLL.
    This is because C++ compiler has "mangled" the function name.

  8. In the OS project, open the TimeDLL subproject.
    Modify the the GetTime function prototype in the header (.h) filer and similarly in the source (.cpp)as follows:

    extern "C"  TimeDLL_API void  GetTime(TCHAR * strTime); 
    That is, prepend extern "C" in both cases.
  9. Rebuild the DLL and rerun the application from the second IDE.

    The modified app should now function correctly.

    Note:
    The C# app did not need recompilation.

     

    image
    Figure 17.x The Managed Code app accessing the native code to get the local time string.

 


NEXT:  17.6 Calling Native Code from VB Managed Code

print

Click here to provide feedback and input

  Comments

There is no comment.

Turkish porno izle video site in rokettubeporno izle