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
tutorial:dlllibrary [2018/09/21 09:57]
admin
tutorial:dlllibrary [2019/03/15 10:42] (current)
admin
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 (จาก Example-1) ​เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\ 
-__ข้อสังเกต__:​ ... +__ข้อสังเกต__: ​ชื่อตัวแปร 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 (จาก Example-1) เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\
 +__ข้อสังเกต__:​ มีดังนี้ \\
 +  *จะต้องมี 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.1537498656.txt.gz · Last modified: 2018/09/21 09:57 by admin