DPI-C export of a task defined inside a SystemVerilog class

Would it be possible to export to C a task defined inside a SystemVerilog class as the following? When this class is instantiated multiple times, does send get treated as a separate task in each instance of the class? Thanks.

class packet_bfm_t;
int id = 0;

export “DPI-C” task send; // Is this possible and legal to call from C code?

function new (int my_id = 0);
id = my_id;
endfunction : new

task send (int data);
#1ns;
$display (“data = %h”, data);
endtask : send

endclass : packet_bfm_t

You can bring it to a wrapper module and export.

In reply to Srini @ CVCblr.com:

Can you elaborate further? Also when this class is instantiated N times, does the task get treated as N different tasks?

In reply to dnguyen82us:
You cannot import/export class methods. Same problem exists between C and C++.

module top;
   class packet;
      static packet list[int];
      int id;
      function new (int my_id);
	 id = my_id;
	 if (list.exists(id))
           $error("id %0d already exists",id);
	 else
           list[id] = this;  
      endfunction : new
      task send (int data);
	 #1ns;
	 $display ("%t id: %0d data = %h", $time,id,data);
      endtask : send
   endclass : packet
   
   task send_wrapper(int id, int data);
      if (packet::list.exists(id))
	packet::list[id].send(data);
      else        
	$error("id %0d does not exist",id);
   endtask
   
   packet h;
   initial begin
      for(int i=1;i<=10;i++) h = new(i);
      call_into_c;
      $display("all done at %t", $time);
   end
   
   import "DPI-C" context task call_into_c();
   export "DPI-C" send = task send_wrapper; 
endmodule : top

C code:

#include "svdpi.h"
int send(int id, int data);
int call_into_c() {
  for(int i=2;i<=11;i++)
    if (send(i,i*i)) return 1;
  return 0;
}

In reply to dave_59:

Thanks, Dave.

My actual problem is this, I have an array of four orthogonal packet senders with task send() defined similar to the code snippet above

class packet_sender_t;
  int id;
  function new (int mid);
    id = mid;
  endfunction
  task send (int data);
    #2ns;
  endtask
endclass

parameter NUM_PORTS = 4;
**packet_sender_t packet_sender [NUM_PORTS];
**
How would I call a particular send task from the C code which knows the index of the packet_sender to send. The main thing is I don’t want to write four wrappers for four packet_sender_t.

Would module (instantiated using loop generate construct) with embedded task work in this case to handle parallel streams of packets?

module new_packet_sender_t;
  task send(int data);
    #2ns;
  endtask
endmodule

genvar i;
for (i = 0; i < NUM_PORTS; i++) begin : scope
  new_packet_sender_t new_packet_sender[i]();
end

Any suggestion would be greatly appreciated.

In reply to dnguyen82us:

there are many ways to associate your packet senders. My method used self-registration, but it can certainly be done externally outside the class or within a module. Calling a module instanciated task requires a scope based context. You might want to see the example I posted here:

https://verificationacademy.com/forums/systemverilog/easy-modelsim-dpi-book#reply-46722