- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am trying to use a derived type structure in a dll subroutine using modules. Here is my main program:
Program Main !dec$ attributes dllimport::_DERIVEDTYPECONSTRCT use PARAM real a,b integer c a=2.0 b=3.0 c=6 allocate (MyArray(1)) call DERIVEDTYPECONSTRCT (1,a,b,c)! deallocate (MyArray) end
the module "Param" is defined as below:
MODULE PARAM type Derived_type real length real width integer measurmentflag end type Derived_type type(Derived_type), allocatable :: MyArray(:) END MODULE
The derived type "MyArray" is declared in the modules and is allocated in the Main program. I want to use is it a subroutine which is defined in a dll project.The subroutine DERIVEDTYPECONSTRCT is built as a dll:
subroutine derivedtypeConstrct (i,x,y,z)! !dec$ attributes dllexport::derivedtypeConstrct !DEC$ ATTRIBUTES STDCALL,ALIAS:"derivedtypeConstrct" :: derivedtypeConstrct !DEC$ ATTRIBUTES REFERENCE :: i,x,y,z use PARAM integer i real x real y integer z MyArray(i)%length=x MyArray(i)%width=y MyArray(i)%measurmentflag=z end
The problem is that when the code enters subroutine derivedtypeConstrct, the array "MyArray" becomes undefined although I have "use PARAM". The code works fine if "MyArray" is not allocatable or if subroutine derivedtypeConstrct is not a dll. I am trying to use the dll later in visual basic where MyArray will be a structure (I am not if it will work though).
Thanks for your helps.
Arash
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There's more than one problem here.
Regarding the array, simply putting the array definition in a module doesn't share it between a DLL and an executable. You have two different copies of MyArray in the program. What you need to do is add:
!DEC$ ATTRIBUTES DLLEXPORT :: MyArray
in the module. When you build the executable, make sure that you don't compile the module again - reference the compiled .mod built by the DLL project (if you make the DLL project a dependent of the executable, this will happen automatically) and link to the export library of the DLL project (to get the object file from the module.) The DLLEXPORT in the module turns into a DLLIMPORT when you "use" it. The DLL project will get an informational message from the linker about a "locally defined" symbol for MyArray, which you can ignore.
Next, you have incorrectly declared the subroutine in the main program. One doesn't put name decoration (the leading underscore) on the ATTRIBUTES line, and you have a mismatch on calling conventions (and name - I am not sure how this even linked.) You need to replace the ATTRIBUTES line you have in the main program with:
!dec$ attributes dllimport::derivedtypeConstrct !DEC$ ATTRIBUTES STDCALL,ALIAS:"derivedtypeConstrct" :: derivedtypeConstrct
Last, you need to make sure that the main program and the DLL both link against the DLL form of the run-time libraries. This is now the default (it wasn't in earlier versions), so it may not be an issue, but check the setting of Fortran > Libraries > Use Runtime Library in both projects to make sure they both name the same DLL library type.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There's more than one problem here.
Regarding the array, simply putting the array definition in a module doesn't share it between a DLL and an executable. You have two different copies of MyArray in the program. What you need to do is add:
!DEC$ ATTRIBUTES DLLEXPORT :: MyArray
in the module. When you build the executable, make sure that you don't compile the module again - reference the compiled .mod built by the DLL project (if you make the DLL project a dependent of the executable, this will happen automatically) and link to the export library of the DLL project (to get the object file from the module.) The DLLEXPORT in the module turns into a DLLIMPORT when you "use" it. The DLL project will get an informational message from the linker about a "locally defined" symbol for MyArray, which you can ignore.
Next, you have incorrectly declared the subroutine in the main program. One doesn't put name decoration (the leading underscore) on the ATTRIBUTES line, and you have a mismatch on calling conventions (and name - I am not sure how this even linked.) You need to replace the ATTRIBUTES line you have in the main program with:
!dec$ attributes dllimport::derivedtypeConstrct !DEC$ ATTRIBUTES STDCALL,ALIAS:"derivedtypeConstrct" :: derivedtypeConstrct
Last, you need to make sure that the main program and the DLL both link against the DLL form of the run-time libraries. This is now the default (it wasn't in earlier versions), so it may not be an issue, but check the setting of Fortran > Libraries > Use Runtime Library in both projects to make sure they both name the same DLL library type.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the reply Steve. In my Dll project I added the export statement for MyArray:
MODULE PARAM !DEC$ ATTRIBUTES DLLEXPORT :: MyArray type Derived_type real length real width integer measurmentflag end type Derived_type type(Derived_type), allocatable :: MyArray(:) END MODULE
and added import statement for MyArray into subroutine derivedtypeConstrct:
subroutine derivedtypeConstrct (i,x,y,z)! use PARAM !dec$ attributes dllexport::derivedtypeConstrct !DEC$ ATTRIBUTES STDCALL,ALIAS:"derivedtypeConstrct" :: derivedtypeConstrct !DEC$ ATTRIBUTES REFERENCE :: i,x,y,z !DEC$ ATTRIBUTES dllimport :: MyArray integer i real x real y integer z MyArray(i)%length=x MyArray(i)%width=y MyArray(i)%measurmentflag=z end
However, when I compile the dll project I get the following error:
error #6401: The attributes of this name conflict with those made accessible by a USE statement. [MYARRAY]
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I didn't say to put in a DLLIMPORT directive for MyArray. Take that out.
Did you also make the necessary changes to the main program?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I removed the DLLIMPORT to MyArray. I made the changes to the main file. everything works fine now if I also remove "!DEC$ ATTRIBUTES REFERENCE :: i,x,y,z" from the subroutine. Do I need the statement?
I want to use the dll in a visual basic code and define a "structure" for MyArray. However, I guess since I don't have "MyArray" in the arguments of the subroutine it won't work.
Thanks,
Arash
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For the ATTRIBUTES REFERENCE line, it has to be in both the subroutine and the main program or neither. (As long as you added the ATTRIBUTES STDCALL with the correct name, along with ALIAS, to the main program.)
For use from VB I recommend keeping REFERENCE in there. You're not going to be able to use MyArray with VB. You may want to look at the two VB examples we provide in MixedLanguage.zip under Samples.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What will be the reference attribute in the main file then?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
See my reply #2 above, where I gave you the lines to be used there. Make sure that you keep the REFERENCE attribute in the subroutine.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much for all the helps Steve.
Arash
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, one last issue. I am compiling using visual studio community 2015. When I call the dll in VB I get the error Unable to find an entry point in DLL. I checked the dll with dependency walker and it cannot find these:
API-MS-WIN-CORE-KERNEL32-PRIVATE-L1-1-1.DLL
API-MS-WIN-CORE-PRIVATEPROFILE-L1-1-1.DLL
API-MS-WIN-SERVICE-PRIVATE-L1-1-1.DLL
However, the dll works fine in VB if I compile with visual studio 2010 shell (which I have installed on another machine). Do I need any special treatment in Community?
Thanks,
Arash
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Are you running this on a different PC than where you built it? If so, download and install (on the target system) the Visual C++ 2015 Redistributables from https://www.microsoft.com/en-us/download/details.aspx?id=48145 You will probably want vc_redist.x86.exe
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a lot Steve. That solved the issue.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page