বৈজ্ঞানিক প্রোগ্রামগুলিতে ফোর্টরানের ফাংশন পয়েন্টারগুলির সাথে কীভাবে কাজ করবেন


11

এখানে সি এর ফাংশন পয়েন্টারগুলির একটি সাধারণ ব্যবহার রয়েছে Fort আমি ফোরট্রানে একই জাতীয় কিছু করতে চাই। আমার কিছু ধারণা আছে তবে আমি জানতে চাই যে এটি করার কিছু যুক্তিযুক্ত উপায় আছে কিনা।

ব্যবহারকারীর দ্বারা পাস করা ফাংশন পয়েন্টার এবং প্রসঙ্গগুলি সংরক্ষণ করা হয়, তারপরে পরে বলা হয়।

typedef PetscErrorCode (*TSIFunction)(TS,PetscReal,Vec,Vec,Vec,void*);
PetscErrorCode TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx);

ব্যবহারকারীর ফাংশনটি বিভিন্ন পরবর্তী সময়ে তাদের প্রসঙ্গ ব্যবহার করে ফিরে কল করা হয়।

পিইটিএসসি তে তারা স্ট্রিং -> ফাংশন পয়েন্টার টেবিলগুলিরও ভারী ব্যবহার করে। সবকিছুই একটি প্লাগইন, যাতে ব্যবহারকারী তাদের নিজস্ব প্রয়োগগুলি নিবন্ধন করতে পারেন এবং তারা প্রথম শ্রেণির।

#define PCGAMG "gamg"
  PCRegisterDynamic(PCGAMG         ,path,"PCCreate_GAMG",PCCreate_GAMG);

এটি তৈরির রুটিনটিকে "FList" তে নিবন্ধভুক্ত করে, তারপরে পিসিসেটফ্রোমপশনস () অন্য যে কোনও পছন্দের তুলনায় এই পদ্ধতিটি বেছে নেওয়ার ক্ষমতা সরবরাহ করে। যদি সিস্টেমটি গতিশীল লোডিং সমর্থন করে, আপনি পিসিসিআরটি_জিএএমজি প্রতীকের উপর সংকলন-সময় নির্ভরতা এড়িয়ে যেতে পারেন এবং কেবল ন্যূআলএল পাস করতে পারেন, তাহলে প্রতীকটি রান সময় শেয়ার করা লাইব্রেরিতে সন্ধান করা হবে।

মনে রাখবেন যে "ফ্যাক্টরি" এর বাইরে এই এক পদক্ষেপটি, এটি মার্টিন ফোলারকে "পরিষেবা লোকেটার" বলার সাথে মিল রেখে কন্ট্রোল ডিভাইসের একটি বিপর্যয়।

দ্রষ্টব্য: এটি আমার জেড ব্রাউনয়ের সাথে আমার ব্যক্তিগত চিঠিতে প্রকাশিত হয়েছিল, যেখানে তিনি আমাকে এই প্রশ্নটি করেছিলেন। আমি এটিকে আউটসোর্স করার সিদ্ধান্ত নিয়েছি এবং লোকেরা কী উত্তর পেতে পারে তা দেখুন see

উত্তর:


5

void *একটি আধুনিক ফোর্টরান কোড অনুকরণ করতে স্থানান্তর ব্যবহার করার দরকার নেই । পরিবর্তে, কেবল আইএসও_সি_বিআইএনডিইং অন্তর্নিহিত মডিউল ব্যবহার করুন , যা সমস্ত মূলধারার ফোর্টরান সংকলক দ্বারা সমর্থিত। এই মডিউলটি খুব সামান্য কিছু ক্যাভ্যাট সহ ফোর্টরান এবং সি এর মধ্যে ইন্টারফেস করা খুব সহজ করে তোলে। ফোর্টরান ডেটা এবং পদ্ধতিতে সি পয়েন্টার পেতে যথাক্রমে কেউ C_LOCএবং C_FUNLOCফাংশন ব্যবহার করতে পারেন ।

উপরের পিইটিএসসি উদাহরণের বিষয়ে, আমি ধরে নিই যে প্রসঙ্গটি সাধারণত ব্যবহারকারী-সংজ্ঞায়িত কাঠামোর জন্য একটি পয়েন্টার, যা ফোরট্রানে প্রাপ্ত ডেটা টাইপের সমান। ব্যবহারের সাথে মোকাবেলা করতে সমস্যা হওয়া উচিত নয় C_LOC। অস্বচ্ছ টিএসআইফিংকশন হ্যান্ডেলটি খুব সহজেই মোকাবেলা করতে পারে: কেবল ISO_C_BINDING ডেটা টাইপ ব্যবহার করুন c_ptr, যা void *সি এর সমতুল্য ফোর্টরানে লিখিত একটি লাইব্রেরি ব্যবহার করতে পারে c_ptrযদি আধুনিক ফোর্টরানের কঠোর ধরণের চেকিংয়ের আশেপাশে কাজ করা দরকার হয়।


ব্রায়ান, হ্যাঁ, ইতিমধ্যে, জেড এবং আমি কলব্যাকের বেশ কয়েকটি সমাধান খুঁজে পেয়েছি , এখানে দেখুন: Fortran90.org/src/best-practices.html#type-casting-in-callbacks , টাইপ (c_ptr) ভি বিভাগের নম্বরটি
হ'ল

9

আপনার অনুমানের অনেকগুলিই আমি অনুমান করছি যে পিইটিএসসি-নির্দিষ্ট ভাষা (যার সাথে আমি অপরিচিত), সুতরাং এখানে একটি বলি হতে পারে যা আমি বেশ বুঝতে পারি না, তবে সম্ভবত এটি আপনাকে পেতে কার্যকর হবে শুরু করেন।

মূলত, আপনাকে পদ্ধতির জন্য ইন্টারফেসটি সংজ্ঞায়িত করতে হবে এবং তারপরে আপনি কোনও ইন্টারফেসটি অনুসরণ করে এমন একটি ফাংশনে একটি পয়েন্টারটি দিতে পারেন। নিম্নলিখিত কোডটি একটি উদাহরণ দেখায়। প্রথমত, একটি মডিউল রয়েছে যা ইন্টারফেসটি সংজ্ঞায়িত করে এবং কোডের একটি অংশের একটি দ্রুত উদাহরণ দেখায় যা সেই ইন্টারফেসটিকে অনুসরণ করে ব্যবহারকারীর সরবরাহিত রুটিন কার্যকর করে। এরপরে একটি প্রোগ্রাম যা দেখায় যে ব্যবহারকারী কীভাবে এই মডিউলটি ব্যবহার করবেন এবং কার্য সম্পাদনের জন্য কার্যটি সংজ্ঞায়িত করবেন।

MODULE xmod

  ABSTRACT INTERFACE
  FUNCTION function_template(n,x) RESULT(y)
      INTEGER, INTENT(in) :: n
      REAL, INTENT(in) :: x(n)
      REAL :: y
  END FUNCTION function_template
  END INTERFACE

CONTAINS

  SUBROUTINE execute_function(n,x,func,y)
    INTEGER, INTENT(in) :: n
    REAL, INTENT(in) :: x(n)
    PROCEDURE(function_template), POINTER :: func
    REAL, INTENT(out) :: y
    y = func(n,x)
  END SUBROUTINE execute_function

END MODULE xmod


PROGRAM xprog

  USE xmod

  REAL :: x(4), y
  PROCEDURE(function_template), POINTER :: func

  x = [1.0, 2.0, 3.0, 4.0]
  func => summation

  CALL execute_function(4,x,func,y)

  PRINT*, y  ! should give 10.0

CONTAINS

  FUNCTION summation(n,x) RESULT(y)
    INTEGER, INTENT(in) :: n
    REAL, INTENT(in) :: x(n)
    REAL :: y
    y = SUM(x)
  END FUNCTION summation

END PROGRAM xprog

উত্তরের জন্য ধন্যবাদ. উপরের পিইটিএসসি উদাহরণটি কিছু অভ্যন্তরীণ ডেটা কাঠামোতে ফাংশন পয়েন্টারও সঞ্চয় করে, তবে আমি মনে করি PROCEDURE(function_template), POINTER :: funcঅভ্যন্তরীণভাবে সংরক্ষণ করা এটি বেশ তুচ্ছ ।
Ondřej Čertík

নোট করুন যে পয়েন্টারটি সেই কোডের ঠিকানার পরিবর্তে একটি অস্বচ্ছ বস্তু, সুতরাং AFAIK সি এর সাথে আন্তঃক্রিয়াশীলতা থাকতে পারে না, পিইটিএসসি-তে, আমাদের এই জিনিসগুলির জন্য সি র‌্যাপারগুলির জন্য ফাংশন পয়েন্টারগুলির সারণীগুলি বজায় রাখতে হবে।
ম্যাট নিপলি

পিইটিএসসি উদাহরণ ফাংশন পয়েন্টার এবং প্রসঙ্গ উভয়ই সংরক্ষণ করে (ব্যক্তিগত ব্যবহারকারী ডেটা যা ফাংশন বলা হয়ে গেলে ফিরে যায়)। প্রসঙ্গটি সত্যই গুরুত্বপূর্ণ, অন্যথায় ব্যবহারকারী রেফারেন্সিং গ্লোবালগুলির মতো ভয়াবহ কাজগুলি শেষ করে। যেহেতু এর কোনও সমতুল্য নেই void*, ব্যবহারকারী তাদের নিজেরাই লাইব্রেরি ফাংশনগুলির জন্য ইন্টারফেস লিখতে শেষ করে। আপনি যদি সিটিতে লাইব্রেরিটি প্রয়োগ করেন তবে এটি যথেষ্ট, তবে আপনি ফোর্টরান এ প্রয়োগ করেন, আপনাকে নিশ্চিত করতে হবে যে সংকলকটি কখনই গ্রাহকের গ্রাহকের "ডামি" ইন্টারফেসটি ব্যবহারকারীর ইন্টারফেসের মতো দেখতে পায় না।
জেড ব্রাউন

2
void*ফরট্রানের সমতুল্য একটি transferপদ্ধতি। ব্যবহারের উদাহরণের জন্য এখানে দেখুন । পদ্ধতির পাশাপাশি অন্য 3 টি পন্থা হ'ল transfer"ওয়ার্ক অ্যারে", "পরিবর্তে নির্দিষ্ট উত্পন্ন ধরণের void *" এবং মডিউলটিতে স্থানীয় মডিউল ভেরিয়েবল ব্যবহার করুন।
Ondřej Čertík

এটি একটি লজ্জার বিষয় যা কেবলমাত্র ফাংশনটি কল করতে ব্যবহারকারীর transferএকটি ননসেন্স ( character (len=1), allocatable)) দিয়ে মজা করতে হবে।
জেদ ব্রাউন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.