1.18.1.2 Access CPlusPlus(.Net) And CSharp DLL


This chapter will introduce how to access the DLL created by C++(.Net) or C# in Origin C.

Access C# Class DLL

The following example shows how to create a DLL in Microsoft Visual Studio 2005 with C#, and then access it in Origin C. This Dll provides a class with properties and functions. Function Sum shows how to pass data array from Origin C vector to C# function.

  1. Run Microsoft Visual Studio as administrator, select File -> New -> Project..., in New Project dialog, choose the settings as below:
    Ocguide externaldll csharp1 newproject.png
  2. Copy the following codes to cs file.
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace temp
    {
        [Guid("4A5BFDFA-7D41-49d1-BB57-C6816E9EDC87")]
        public interface INet_Temp
        {
            double Celsius{ get; set; }
            double Fahrenheit{ get; set; }
     
            double GetCelsius();
            double GetFahrenheit();
    
            double Sum(object obj);
        }
    }
    
    namespace temp
    {
        [Guid("2AE913C6-795F-49cc-B8DF-FAF7FBA49538")]
        public class NET_Temperature : INet_Temp
        {
            private double celsius;
            private double fahrenheit;
    
            public NET_Temperature()
            {
            }
    
            public double Celsius
            {
                get{ return celsius; }
                set { celsius = value; fahrenheit = celsius + 273.5;  }
            }
            public double Fahrenheit
            {
                get { return fahrenheit; }
                set { fahrenheit = value; celsius = fahrenheit - 273.5; }
            }
    
            public double GetCelsius()
            {
                return celsius;
            }
            public double GetFahrenheit()
            {
                return fahrenheit;
            }      
    
            public double Sum(object obj)
            {
                double[] arr = (double[])obj;
                double sum = 0.0;
                for (int nn = 0; nn < arr.Length; nn++)
                {
                    sum += arr[nn];
                }
                return sum;
            } 
        }
    }
  3. Choose menu Tools -> Create GUID, in opening dialog select Registry Format radio button, click New GUID button and then click Copy button. Paste this GUID to replace that one in [Guid("...")] in the above codes. Reproduce this action again to replace the second GUID in code.
  4. Right click on the project and select Properties to open the property page. Go to Application tab, and click Assembly Information button, then check the check-box of Make assembly COM-Visible. If for 32 bit version, go to the Build tab, and select the check-box of Register for COM interop. If for 64 bit version, go to Build Events tab, and then copy and paste the following command line to the Post-build event command line text box. Press F6 to build solution.
  5. "%Windir%\Microsoft.NET\Framework64\v4.0.30319\regasm" "$(TargetPath)" /CodeBase
  6. Start Origin, open Code Builder, new a c file, then copy the following Origin C code to c file.
    void access_DLL()
    {
    	Object obj = CreateObject("temp.NET_Temperature");
    	
    	obj.Celsius = 0; // access property
    	out_double("", obj.GetFahrenheit()); // access function
    	
    	obj.Fahrenheit = 300;
    	out_double("", obj.GetCelsius());
    
    	vector vec;
    	vec.Data(1,10,1);
    	_VARIANT var = vec.GetAs1DArray();
    	out_double("", obj.Sum(var));
    }

Access C# and C++ Resource DLL

The following shows how to create an ActiveX control by C#, and use it in a dialog in Origin C.

Steps 1~7 shows how to create an C# ActiveX control in Microsoft Visual Studio 2005.

  1. Start Microsoft Visual Studio 2005, choose File -> New -> Project... to open New Project dialog, do the following settings, then click OK button.
    Ocguide externaldll csharp2 newproject.png
  2. Copy the following codes to UserControl.cs file to add a protected override function to set control fill color and a public function to set control border.
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace SampleControl
    {
        [Guid("A31FE123-FD5C-41a1-9102-D25EBD5FDFAF"),
        ComSourceInterfaces(typeof(UserEvents)),
        ClassInterface(ClassInterfaceType.None),]
        public partial class UserControl1 : UserControl, UserControl1Interface
        {
            public UserControl1()
            {
                InitializeComponent();
            }
    
            protected override void OnPaint(PaintEventArgs pe)
            {
                Brush brush = new SolidBrush(Color.Beige);
    
                pe.Graphics.FillRectangle(brush, ClientRectangle);
            }
    
            public void SetBorder(bool bSet)
            {
                this.BorderStyle = bSet ? BorderStyle.FixedSingle :
                            BorderStyle.None;
                Refresh();
            }
        }
    
        //declare an Interface for the control settings
        [Guid("CCBD6133-813D-4dbb-BB91-16E3EFAE66B0")]
        public interface UserControl1Interface
        {
            void SetBorder(bool bSet);
        }
    }
  3. Select Tools -> Create GUID to open Create GUID dialog, choose Registry Format radio button, click New GUID and Copy button to copy the newly created GUID. Use the new GUID to replace the one in above code [Guid("...")].
  4. Choose UserControl1.cs[Design] tab, in Properties window, click Events button Ocguide externaldll csharp2 eventbutton.png, drag scroll bar to choose MouseClick and double click it to add mouse click event function into UserControl.cs file. Use the same method to add mouse double click event.
  5. In UserControl1l.cs file, copy the following code outside UserControl1 class.
    //declare delegates for events 
    public delegate void MouseAction(int x, int y);
  6. In UserControl1 class, add the following implements.
    public event MouseAction OnUserClick;
    public event MouseAction OnUserDbClick;
    
    private void UserControl1_MouseClick(object sender, MouseEventArgs e)
    {
          if (OnUserClick != null)
          {
              OnUserClick(e.X, e.Y);
          }
    }
    
    private void UserControl1_MouseDoubleClick(object sender, MouseEventArgs e)
    {
          if (OnUserDbClick != null)
          {
              OnUserDbClick(e.X, e.Y);
          }
    }
  7. Outside UserControl1 class, add the following interface.
    //declare interface for events
    [Guid("DA090A6F-FFAC-4a39-ACD3-351FA509CA86"), 
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface UserEvents
    {
        [DispIdAttribute(0x60020001)]
        void OnUserClick(int x, int y);
    
        [DispIdAttribute(0x60020002)]
        void OnUserDbClick(int x, int y);
    }
  8. Create a resource-only DLL in Visual Studio 2008 as explained in Dialog Builder: Simple Hello World Dialog: Create Resource-only DLL in Visual Studio 2008
  9. Use an ActiveX control in a dialog and show dialog by Origin C. In Origin Code Builder, create a c file, and copy the following code to it.
    //Dialog and control Ids. Need change dialog id according to real case.
    #define IDD_DIALOG1                     101
    #define IDC_DOTNET						1000
    
    //Exposed events from Control
    #define	ON_INTEROP_CLICK(_idCntl, _ocFunc)	
    ON_ACTIVEX_EVENT(0x60020001, _idCntl, _ocFunc, VTS_CTRL VTS_I4 VTS_I4)
    
    #define	ON_INTEROP_DBLCLICK(_idCntl, _ocFunc)	
    ON_ACTIVEX_EVENT(0x60020002, _idCntl, _ocFunc, VTS_CTRL VTS_I4 VTS_I4)
    
    
    class CDotNetComInteropDlg : public Dialog
    {
    public:
    	CDotNetComInteropDlg();
    
    	EVENTS_BEGIN
    	ON_INIT(OnInitDialog) 
    	//Event handler entries for the exposed events
    	ON_INTEROP_CLICK(IDC_DOTNET, OnClick)
    	ON_INTEROP_DBLCLICK(IDC_DOTNET, OnDblClick)
    	EVENTS_END
    	
    	BOOL OnClick(Control ctrl, int x, int y)
    	{
    		printf("Clicked at (%d,%d)\n", x,y);
    		return true;
    	}
    	
    	BOOL OnDblClick(Control ctrl, int x, int y)
    	{
    		printf("DblClicked at (%d,%d)\n", x,y);
    		return true;
    	}
    
    	
    	BOOL OnInitDialog();
    	
    	Control m_ctrlDotNet;
    };
    
    
    // Do not specify DLL file path here. Assume the dll file under the same 
    // path with the current c file.
    CDotNetComInteropDlg::CDotNetComInteropDlg()
    	: Dialog(IDD_DIALOG1, "DialogBuilder.dll")
    {
    	InitMsgMap();
    }
    
    
    BOOL CDotNetComInteropDlg::OnInitDialog()
    {	
    	//[Guid("A31FE123-FD5C-41a1-9102-D25EBD5FDFAF")]
    	GUID guid = {0xA31FE123, 0xFD5C, 0x41a1, 
    		{0x91, 0x02, 0xD2, 0x5E, 0xBD, 0x5F, 0xDF, 0xAF}};
    	
    	RECT rect = {20,20,200,100};
    	if(m_ctrlDotNet.CreateActiveXControl(guid, WS_CHILD|WS_VISIBLE,
    		rect, GetSafeHwnd(), IDC_DOTNET))
    	{
    		//Control intialization using the exposed interface of 
    		//the DotNet control
    		Object ctrlObj = m_ctrlDotNet.GetActiveXControl();
    		ctrlObj.SetBorder(true);
    	}
    	return TRUE;
    }
    
    void Launch_CDotNetComInteropDlg()
    {
    	CDotNetComInteropDlg dlgDotNet;
    	dlgDotNet.DoModal();
    }