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/10/28 09:12]
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 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 79: Line 79:
 =====การเรียกใช้งาน Shared Library===== =====การเรียกใช้งาน Shared Library=====
 การเรียกใช้งาน Shared Library สามารถเรียกได้ 2 แบบ ดังนี้ การเรียกใช้งาน Shared Library สามารถเรียกได้ 2 แบบ ดังนี้
-  *Static Calling คือการเรียกในขณะ Compile-time นั่นหมายถึงเวลาที่เราำไฟล์ .exe ไปแจ่ายนั้น ไมจำเป็นตองบไฟล์ .dll ไปใน Folder ​นื่องจาก code ต่างๆใน Shared Library ได้ถูก compiled ไว้ใไฟล์ ​.exe เรียบรอยแว วิธีเรียกแบบนี้ีข้อดีคือไม่ซัซ้อน แต่มีข้อเสียคือจะทำให้ไฟล์ของโปรแกรมที่เราเขียนขึ้น ​มีขนาดใหญ่ +  *Static Calling คือการเรียกทุก function จก Library ​มาเก็บไ้ใแกรมหลักตั้งแตต้น ยกัวย่าง เช่น เราต้องการใช้น function ทั้งหมด 5 ตัว ทุกครังที่มีารรัน .exe function ทัง 5 ตัวดังก่าว ก็จะถูกเรียกมาเก็นโปรแกรมเราตั้งแต่ต้น  
-  *Dynamic Calling คือการเรียกใช้ ​ในขณะ Run-time นั่นคือเวลาที่เรานำไฟล์ .exe ไปแกจ่ยนั้น จำเป็นต้องแนบไฟล์ .dll ไปใน Folder ทุครั้ง ​เพาะตัว ​Shared Library ไมได้ถูก ​Compiled ​เขากับฟล์ .exe ังนันจึงถูกเรียกมาใช้เฉพาะน้แทน ​วิธีเรียกแบบนี้จะต้องเขียน ​code ที่ค่อนข้าุ่ก แตอดคืจะทำห้ขนาดของโปรแกรเราไม่ใญ่มากและรายังสามารถ Update ​ไฟล์ .dll ได้นภยหลัง+  *Dynamic Calling คือการเรียกใช้ ​function ​จาก ​Library ​พาะตัวที่ถูกใช้งานจิง ไได้เรียกมาใช้ทั้งมดแต่แรก อย่งไรก็ตาม ​วิธีนี้จะยุ่งยากกว่าวิธีแรกพอสมควร เพราะต้องเขียน ​procedure/​function ​นมเป็นพิเศษเพื่อเรีกใช้งาน function เหลานันทละตัว ขครของมัน\\ 
 +หมาหตุ: ทงสองแบบ ต้องการไฟล์ .dll แนบช้งนกับไฟ์ .exe ด้วยทุกครง 
  
 <hidden Example-2: Static Calling .dll Library> <hidden Example-2: Static Calling .dll Library>
Line 112: 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 129: Line 183:
 |  oldfpccall ​ |  RTR  |  Callee ​ | |  oldfpccall ​ |  RTR  |  Callee ​ |
  
-จากตารางข้างบนอธิบายถึงความต่างของแต่ละ Calling Convention ​ือทิศทางการใส่ค่าตัวแปร และการกำจัดค่าของตัวแปรใน Ram จะเห็นได้ว่า default, register และ pascal จะมีการใส่ค่าตัวแปรแบบ "​ซ้ายไปขวา"​ หรือ LTR (Left-to-Right) ในขณะที่ cdecl, interupt, safecall, stdcall และ oldfpccall จะใส่ค่าตัวแปรแบบ "​ขวาไปซ้าย"​ หรือ RTL (Right-to-Left) ​+จากตารางข้างบนอธิบายถึงความต่างของแต่ละ 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 ใน .dll ไม่ตรงกับการเรียกใช้ในไฟล์ .exe ก็อาจทำให้เกิดการใส่ตัวแปรในแต่ละ Argument ของ Procedure/​Function สลับกันได้ จะนำไปสู่การคำนวณที่ผิดพลาดอย่างแน่นอน ​
 \\ \\ \\ \\
-**__หมายเหตุ__** - การไม่ระบุ Calling Convention นั้น จะหมายถึงการเรียกใช้งานแบบ default ซึ่งตัว ​default สำหรับ FPC คือ register +**__หมายเหตุ__** - การไม่ระบุ Calling Convention นั้น จะหมายถึงการเรียกใช้งานแบบ default ซึ่ง default ​calling convention ​สำหรับ FPC คือ register 
-<hidden Example-3: Static Calling .dll Library using stdcall as calling convention>​+<hidden Example-4: Static Calling .dll Library using stdcall as calling convention>​
 **ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\ **ตัวอย่าง** การเรียก Library ชื่อว่า Pipe เพื่อเก็บฟังก์ชั่นคำนวณหาพื้นที่หน้าตัดท่อ\\
-__ข้อสังเกต__:​ จะต้องมีการระบุ Calling Convention ทั้งใน .dll และโปรแกรมหลัก \\+__ข้อสังเกต__: ​เราจะใช้ Calling ที่ชื่อว่า stdcall ซึ่งจะต้องมีการระบุ Calling Convention ทั้งใน .dll และโปรแกรมหลัก \\
  
 <sxh delphi;​highlight:​ [8,13]> <sxh delphi;​highlight:​ [8,13]>
tutorial/dlllibrary.txt · Last modified: 2019/03/15 10:42 by admin