既然说到了C#,那么一奶同胞的怎么能忽略呢?
Visual Basic .Net和C#的内核完全一样,都是.Net,只是外在的语言形式不一样。这种情况下,调用CChart的方法也非常类似。
总的说来,就是采用C风格代码,并把代码翻译到对应的语言。
在C#里面,笨笨做了一个简单的包装,导出了一部分常用的函数,这样简化了同学们的使用。
在里面,笨笨不想再越俎代庖了,还是大家自己操刀吧。
不多说了,下面用例子说话。
首先还是介绍一下关键的知识点。
前面C#里面调用C++的函数,采用了DllImport。里面调用C++函数同样可以采用DllImport,只是调用的格式有所区别。如下所示。
<DllImport("CChartu.dll", EntryPoint:="?CreateChart@Classless@@YAXXZ", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Sub CreateChart()End Sub
这里同样需要到CChartu_EXPORTS.txt里面查找函数入口点?CreateChart@Classless@@YAXXZ。
其实还有一种导入函数的方法,形式上要简单一些。
Private Declare Sub CreateChart Lib "CChartu.dll" Alias "?CreateChart@Classless@@YAXXZ" ()
为什么不采用这种方法呢?主要是因为这种方法无法指定函数调用的cdecl约定,而是使用默认的stdcall约定,和CChart的cdecl约定不同,运行时会出现堆栈错误。当然理论上笨笨可以把CChart的调用约定修改为stdcall,不过这样改动太大,还是算了吧。
下面正式开始。
第一步,用Vs建立一个Visual Basic .Net的Windows窗体应用程序,如图。
第二步,右键点击Form1窗体,选择“查看代码”。然后在Public class Form1的下一行,添加如下导入函数的代码。
<DllImport("CChartu.dll", EntryPoint:="?CreateChart@Classless@@YAXXZ", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Sub CreateChart()End Sub<DllImport("CChartu.dll", EntryPoint:="?Attach@Classless@@YAHPAUHWND__@@@Z", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Function Attach(ByVal hWnd As IntPtr) As IntegerEnd Function<DllImport("CChartu.dll", EntryPoint:="?ReDraw@Classless@@YAXXZ", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Sub ReDraw()End Sub<DllImport("CChartu.dll", EntryPoint:="?AddPoint2D@Classless@@YAHNNHH@Z", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Function AddPoint2D(ByVal x As Double, ByVal y As Double, ByVal DataIndex As Integer, ByVal PlotIndex As Integer) As IntegerEnd Function<DllImport("CChartu.dll", EntryPoint:="?SetTitle@Classless@@YAXPB_W@Z", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)>Public Shared Sub SetTitle(ByVal title() As Byte)End Sub
这里导出了下面将要用到的5个函数,这是整个过程中工作量最大的部分。
第三步,通过Form1的属性对话框,添加Load行为。
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadDim mHandle As IntPtr = Me.Handle()CreateChart()Attach(mHandle)For i As Integer = -10 To 10AddPoint2D(i, i * i, 0, 0)NextDim title() As Byte = System.Text.Encoding.Unicode.GetBytes("测试")SetTitle(title)End Sub
注意这里获得主窗口句柄的方法,这是整个代码的关键之处。
另外这里还有一点,要注意字符串参数应采用ByVal title() As Byte这样的字符数组,同时在调用含字符串参数的函数时,应先把字符串转换为Byte数组,不然会显示乱码。
第四步,通过Form1的属性对话框,添加布局操作Resize。
Private Sub Form1_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ResizeReDraw()End Sub
代码到此为止了,效果如图。
可以看出,的编程和C#没有什么大的区别。
同样的情况,如果需要在里面绘制等高线图,可以用委托来实现函数指针,具体方法和上一课C#的委托基本相同,这里也就不再专门讲解了。