Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Breaking a DLL into separate DLLs

Ibrahim_A_
Novice
2,844 Views

Hello Community,

I currently have two Projects that are connected and work perfectly. There's a static library Project (exe) that calls a dynamic library project (dll). The DLL project consists of many Modules. I would like to break the DLL project into separate DLLs by compiling each module as an individual DLL.

Would you guide me where to find instructions on this? I am using Visual Studio to build the projects.

0 Kudos
25 Replies
jimdempseyatthecove
Honored Contributor III
736 Views

The problem you have is array (allocatable) descriptors in Fortran differ from C# [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] array.

Try this:

    type, BIND(C) sum_data
        real(8):: x(3),y(3),sumt(3)
    end type sum_data

*** and remove the allocation in the Fortran code

you cannot perform allocations in Fortran and destroy in C#
you cannot perform allocations in C# and deallocate in Fortran

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
733 Views

It is possible to use allocatable and assumed-shape arrays between C and Fortran (to the extent that you can make C# look like C), but this involves using the C interoperability features from Fortran 2018 (supported as of ifort 16), "C descriptors" and calls to Fortran compiler provided CFI_xxx routines. It's doable, but if you don't need that then Jim's advice is a better bet.

0 Kudos
Ibrahim_A_
Novice
702 Views

Thank you Steve. I'd like to go with the assumed-shape approach. The idea is that I want the array to be allocated inside the fortran dll. Do you have an example or references that I can look at?

0 Kudos
Steve_Lionel
Honored Contributor III
693 Views

Here is an example I have used. It uses allocatable, deferred-length strings but the basic idea is there.

C++ caller:

#include "ISO_Fortran_binding.h"
#include <memory.h>
#include <stdio.h>

extern "C" void greetings(CFI_cdesc_t * descr);

int main()
{
	int status;
	CFI_CDESC_T(0) cdesc;

	// Create our own local descriptor for an allocatable string
	status = CFI_establish((CFI_cdesc_t *)&cdesc, NULL, CFI_attribute_allocatable,
 		                CFI_type_char, 1, 0, NULL);
	//Allocate the string to length 7
	status = CFI_allocate((CFI_cdesc_t *)&cdesc, NULL, NULL, 7);
	// Copy in 'Hello, '
	memcpy(cdesc.base_addr, "Hello, ", 7);
	// Call Fortran to append to the string and print it
	greetings((CFI_cdesc_t *)&cdesc);
	printf("Length is now %zd\n", cdesc.elem_len);
	status = CFI_deallocate((CFI_cdesc_t *)&cdesc);
}

Fortran subroutine:

subroutine greetings (string) bind(C)
    implicit none
    character(:), allocatable :: string
    
    string = string // 'Zurich!'
    print *, string
    end subroutine greetings

 

0 Kudos
Steve_Lionel
Honored Contributor III
689 Views

In your case you would not call CFI_ALLOCATE, but would pass the descriptor into the Fortran routine. In Fortran, you'd do an ALLOCATE on the allocatable array argument, and back in C++ you could get the base address from the descriptor.

0 Kudos
Reply