User Tools

Site Tools


tutorial:dlllibrary

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
tutorial:dlllibrary [2018/09/21 09:57]
admin
tutorial:dlllibrary [2019/01/04 12:04]
admin [การระบุ Calling Convention]
Line 8: Line 8:
 |  Linux  |  .so  | |  Linux  |  .so  |
 |  MacOS X  |  .dylib ​ |  |  MacOS X  |  .dylib ​ | 
-\\ \\+\\ 
 =====การสร้าง Shared Library===== =====การสร้าง Shared Library=====
 ใน Lazarus IDE เราสามารถสร้าง Shared Library ไว้ใช้งานสำหรับ Window, Linux และ MacOS X ได้ทั้งหมดครับ โดยการเลือกเมนู \\ ใน Lazarus IDE เราสามารถสร้าง Shared Library ไว้ใช้งานสำหรับ Window, Linux และ MacOS X ได้ทั้งหมดครับ โดยการเลือกเมนู \\
Line 37: Line 37:
 end; end;
  
-exports ​FunctionName1;+exports ​FunctionName;
  
 begin begin
Line 47: Line 47:
   Run >> Compile   Run >> Compile
  
-เมื่อทำการ compile เสร็จเรียบร้อย เราจะได้ไฟล์ .dll ที่พร้อมใช้งานครับ ​+เมื่อทำการ compile เสร็จเรียบร้อย เราจะได้ไฟล์ .dll ที่พร้อมใช้งานครับ ​ให้นำไฟล์ .dll ไปไว้ใน folder เดียวกับไฟล์ Project เราได้เลย
  
 <hidden Example-1: Create .dll Library> <hidden Example-1: Create .dll Library>
Line 59: Line 59:
   SysUtils, Classes, Math;   SysUtils, Classes, Math;
  
-function PipeArea1(const DOut,​DIn ​ : double) : double;+function PipeArea1(const DOut,​DIn ​ : double) : double; ​{Calling;}
 begin begin
   result := (PI/​4)*(DOut*DOut - DIn*DIn);   result := (PI/​4)*(DOut*DOut - DIn*DIn);
 end; end;
  
-function PipeArea2(const DOut,​tw ​ : double) : double; ​+function PipeArea2(const DOut,​tw ​ : double) : double; ​{Calling;​} ​
 begin begin
   result := (PI/​4)*(DOut*DOut - (DOut-2*tw)*(DOut-2*tw));​   result := (PI/​4)*(DOut*DOut - (DOut-2*tw)*(DOut-2*tw));​
 end; end;
  
-exports PipeArea1, +exports PipeArea1,​PipeArea2;​
-PipeArea2;+
  
 begin begin
Line 80: Line 79:
 =====การเรียกใช้งาน Shared Library===== =====การเรียกใช้งาน Shared Library=====
 การเรียกใช้งาน Shared Library สามารถเรียกได้ 2 แบบ ดังนี้ การเรียกใช้งาน Shared Library สามารถเรียกได้ 2 แบบ ดังนี้
-  *Static Calling คือการเรียกมาในขณะ Compile-time วิธีรียแบนี้ไม่ซบซอน ​แต่มีขอเสีคืจะทำใหไฟล์ของโปรแกรมที่ราเียนขึ้น ​ีขนหญ่ +  *Static Calling คือการเรียกทุก function จาก Library ​มาเกบไว้ในโปรแกรหลักตั้แต่น กตัวย่าง เช่น เราต้องกใช้งาน function ทั้งหด 5 ตัว ทุกครั้งที่มีการัน .exe function ทั้ง 5 ตัวดังกล่ว ก็จะถูกียมาเก็บนโปรแกรมเราตั้งแตต้น ​ 
-  *Dynamic Calling คือการเรียกใช้ ​ในขณะ Run-time ​ิธีเรียกแบบนี้จะต้องเขียน ​code ที่ค่อนข้างยุก แตอดคือ จทำห้ขนาดของโปรแกรมเราไม่หญ่มาก+  *Dynamic Calling คือการเรียกใช้ ​function จาก Library เฉพาตั่ถูกใช้งานจริง ไม่ได้เรียกมาใช้ทั้งหมดต่แรก อย่างไรก็ตาม วิธีนี้จะยุ่งยากกว่าวิธีแรกพอสมควร เพราะต้องเขียน ​procedure/​function ​นมเป็นพิเศษเพือเรียกใช้งาน function เหลานันทตัว ของครองมั\\ 
 +หมยเหตุ:​ ทั้งสองแบบ ต้องกาฟล์ .dll แนบไปช้งับไฟล์ .exe ด้วยทุกครั้ง ​
  
 <hidden Example-2: Static Calling .dll Library> <hidden Example-2: Static Calling .dll Library>
 **ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\ **ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\
-__ข้อสังเกต__:​ ..+__ข้อสังเกต__: ​ชื่อตัวแปร Argument ของในโปรแกรมนี้ ไม่ตรงกับใน ​.dll \\ 
 +  *ไฟล์นี้ ใช้ PipeArea1(const D,​Di:​double):​double \\ 
 +  *แต่ในไฟล์ ​.dll ใช้ PipeArea1(const DOut,​DIn ​ : double) : double; \\ 
 +จะเห็นว่าชื่อตัวแปรสามารถตั้งให้ต่างกันได้ เพียงแต่ต้องเป็นชนิดเดียวกัน
 <sxh delphi;> <sxh delphi;>
 program StaticCalling_PIPEDLL;​ program StaticCalling_PIPEDLL;​
Line 96: Line 99:
   Classes;   Classes;
  
-function PipeArea1(const D,​Di:​double):​double;​ external '​Pipe.dll';​ +function PipeArea1(const D,​Di:​double):​double;​{calling;​} ​external '​Pipe.dll';​ 
-function PipeArea2(const D,​t:​double):​double;​ external '​Pipe.dll';​+function PipeArea2(const D,​t:​double):​double;​{calling;​} ​external '​Pipe.dll';​
  
 Var D,​Di,​t:​double;​ Var D,​Di,​t:​double;​
Line 110: Line 113:
   readln;   readln;
  
 +end. 
 +</​sxh> ​    
 +</​hidden>​
 +
 +<hidden Example-3: Dynamic Calling .dll Library>
 +**ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\
 +__ข้อสังเกต__:​ มีดังนี้ \\
 +  *จะต้องมี unit ชื่อ Dynlibs\\
 +  *จะต้องมีการเรียกใช้ function เป็นตัวแปร หรือที่เรียกว่า Procedural Type \\
 +<sxh delphi;​highlight:​ [8,​13-14,​20-35,​42]>​
 +program DynamicCalling_PIPEDLL;​
 +//This example demonstrates the simple use of static/​Dynamic calling.
 +//For calling convention, register is used by default.
 +
 +{$mode objfpc}{$H+}
 +
 +uses
 +  Classes,​Dynlibs;​
 +
 +function PipeArea1(const D,​Di:​double):​double;​{calling;​} external '​Pipe.dll';​
 +
 +//Define procedural type for Dynamic Calling
 +type
 +  TMyDLL = function(const D,​Di:​double):​double;​{calling;​}
 +
 +
 +
 +Var D,​Di:​double;​
 +
 +  function CallDLib(const D,​Di:​double):​double;​
 +  var
 +    MyHandle: TLibHandle;
 +    MyDLLFunc: TMyDLL;
 +  begin
 +    MyHandle := SafeLoadLibrary('​Pipe.dll'​);​
 +    if MyHandle<>​0 then
 +      begin
 +        MyDLLFunc := TMyDLL(GetProcedureAddress(MyHandle,'​PipeArea1'​));​
 +        if Assigned(MyDLLFunc) then
 +          result:​=MyDLLFunc(D,​Di);​
 +      end
 +    else
 +      result:=10;
 +    FreeLibrary(MyHandle);​
 +  end;
 +
 +begin
 +  writeln('​Example for calling .dll library named Pipe.dll'​);​
 +  D:=0.25;
 +  Di:=0.23;
 +  writeln('​Static Calling PipeArea1(D,​Di):​ ',​PipeArea1(D,​Di));​
 +  writeln('​Dynamic Calling PipeArea1(D,​Di):​ ',​CallDLib(D,​Di));​
 +  readln;
 end.  end. 
 </​sxh> ​     </​sxh> ​    
Line 127: Line 183:
 |  oldfpccall ​ |  RTR  |  Callee ​ | |  oldfpccall ​ |  RTR  |  Callee ​ |
  
-แต่สำหรับ่ระบุนั้น ​compiler ​ะรู้ได้อง่าเราำลังใช้แบบ default ซึ่งนที่น้ก็คือ register+จากตารางข้างบนอธิบายถึงความต่างของแต่ละ Calling Convention มีทั้งเรื่องทิศทางการใ่ค่าตัวแปร และการกจัดค่าของตัวแปรใน Ram จะเ็นได้ว่า default, register และ pascal จะมีกาใส่ค่าตวแปรแบ "​ซ้ปขวา"​ หรือ LTR (Left-to-Right) ในขณะที่ cdecl, interupt, safecall, stdcall และ oldfpccall จะใส่ค่าตัวแปรแบบ "​ขวาไปซ้าย"​ หรือ RTL (Right-to-Left)  
 +\\ \\ 
 +**__ข้อควรระวัง__** - หากเราระบุ ​Calling Convention ใน .dll ไม่ตรงกบการเรียกใชไฟล์ .exe ก็อาทำใหเกิดการใส่ตัวแปรในแต่ละ Argument ของ Procedure/​Function สลับกันได้ ​จะนำไปสู่การคำนวณที่ผิดพลาดย่าแนนอน  
 +\\ \\ 
 +**__หมหตุ__** - ารไม่ระบุ Calling Convention น้น จะหมายถึการเรียกใช้งานแบบ default ซึ่ง ​default calling convention สำหรับ FPC คือ register 
 +<hidden Example-4: Static Calling .dll Library using stdcall as calling convention>​ 
 +**ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่น้าตัดท่อ\\ 
 +__ข้อสังเต__: เราจะใช้ Calling ที่ชว่า stdcall ซึ่งจะต้องมีการระบุ Calling Convention ทั้งใน .dll และโปรแกรมหลัก \\ 
 + 
 +<sxh delphi;​highlight:​ [8,​13]>​ 
 +library Pipe; 
 + 
 +{$mode objfpc}{$H+} 
 + 
 +uses 
 +  SysUtils, Classes, Math; 
 + 
 +function PipeArea1(const DOut,​DIn ​ : double) : double; stdcall; 
 +begin 
 +  result := (PI/​4)*(DOut*DOut - DIn*DIn); 
 +end; 
 + 
 +function PipeArea2(const DOut,​tw ​ : double) : double; stdcall; 
 +begin 
 +  result := (PI/​4)*(DOut*DOut - (DOut-2*tw)*(DOut-2*tw));​ 
 +end; 
 + 
 +exports PipeArea1,​ 
 +PipeArea2;​ 
 + 
 +begin 
 +end. 
 +</​sxh> ​    
 + 
 +<sxh delphi;​highlight:​ [10-11]>​ 
 +program StaticCalling_PIPEDLL;​ 
 +//This example demonstrates the simple use of static calling .dll library. 
 +//For calling convention, ​register ​is used by default. 
 + 
 +{$mode objfpc}{$H+} 
 + 
 +uses 
 +  Classes; 
 + 
 +function PipeArea1(const D,​Di:​double):​double;​ stdcall; external '​Pipe.dll';​ 
 +function PipeArea2(const D,​t:​double):​double;​ stdcall; external '​Pipe.dll';​ 
 + 
 +Var D,​Di,​t:​double;​ 
 + 
 +begin 
 +  writeln('​Example for calling .dll library named Pipe.dll'​);​ 
 +  D:=0.25; 
 +  Di:=0.23; 
 +  t:=0.013; 
 +  writeln('​Calling PipeArea1(D,​Di):​ ',​PipeArea1(D,​Di));​ 
 +  writeln('​Calling PipeArea2(D,​t):​ ',​PipeArea2(D,​t));​ 
 +  readln; 
 + 
 +end.  
 +</​sxh> ​     
 +</​hidden>​ 
 \\ \\ \\ \\
 =====References===== =====References=====
 https://​www.freepascal.org/​docs-html/​prog/​progsu7.html \\ https://​www.freepascal.org/​docs-html/​prog/​progsu7.html \\
 https://​www.freepascal.org/​docs-html/​prog/​progse22.html#​x173-1760006.3 https://​www.freepascal.org/​docs-html/​prog/​progse22.html#​x173-1760006.3
tutorial/dlllibrary.txt · Last modified: 2019/03/15 10:42 by admin