在不使用 LoadLibrary 的情况下从 C DLL 调用 Fortran DLL (Visual Studio)
Call Fortran DLL from a C DLL without using LoadLibrary (Visual Studio)
我有一些编译为 dll 对象的 C 代码。
我有一个单独的项目,用 Fortran 编写,我也将其编译为单个 dll 对象。
我需要从 C dll 调用 Fortran dll 中的函数,而不使用 LoadLibrary。我还需要 2 个 dll 保持独立,这样我就可以替换一个或另一个而无需重新编译它们。
我已经阅读了一些关于该主题的信息,但我无法让它发挥作用。编译器不会抛出错误或警告,但是当我启动主程序时它会失败。这是我尝试过的:
我已经用 BIND ("C", NAME="FUNCNAME")
声明了我希望从 C 代码调用的所有函数
我在里面声明了USE, INTRINSIC :: ISO_C_Binding
我打算从 C 代码调用的函数和子例程
我在 Fortran 中包含了 !DEC$ ATTRIBUTES DLLEXPORT :: NAME
代码(我正在使用 ifort)
我在我的 Fortran 代码中使用了 c 类型的变量
我在C代码中通过引用传递变量
我将 Fortran dll .lib 文件作为源文件包含到 C 项目中
根据我查阅的大多数资料和文档,我应该能够简单地执行以下操作:
在 Fortran 中:
SUBROUTINE FORTRANDLLFUNCTION(arg1, arg2, arg3, char1) BIND (C, NAME='FORTRANDLLFUNCTION')
USE, INTRINSIC :: ISO_C_Binding
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANDLLFUNCTION
REAL(C_FLOAT), INTENT(INOUT) :: arg1
REAL(C_FLOAT), INTENT(INOUT) :: arg2
REAL(C_FLOAT), INTENT(INOUT) :: arg3
CHARACTER(KIND=C_CHAR), INTENT(IN ) :: char1
<do stuff>
END SUBROUTINE FORTRANDLLFUNCTION
在 C:
extern void FORTRANDLLFUNCTION(float**, float**, float**, char*, int);
float a, b, c;
char abc;
FORTRANDLLFUNCTION(&a, &b, &c, abc, sizeof(abc));
但是,运行在主程序中出现错误。如果我删除对 Fortran 函数的调用和 运行 带有已编译 C dll 的主程序,它就可以工作。我的问题的根源是什么?
这是 dumpbin /exports
在已编译的 Fortran dll 上的输出:
这是 dumpbin /imports
在已编译的 C dll 上的结果:
所以我终于找到了问题的原因...
我放弃了这个并专注于项目的不同部分,这让我发现我得到这个错误的原因是 Fortran dll 不必与C dll,但与调用 C dll 的 exe 相同的目录(C dll 位于不同的位置)。
这真的让我感到惊讶,因为我收到的错误是“无法加载 C.dll”,而不是“无法 find/load fortran.dll”,正确的回溯或消息可以节省我几个小时...
无论哪种方式,如果不是@Mgetz 的评论,我相信它无论如何都不会奏效,所以非常感谢,真的!
对问题的一些评论进行更多说明:
在我最终意识到解决方案是什么之前,除了使用 cmake .. -G "Visual Studio 17 2022" -A x64
创建我的 VS 项目之外,我还在 Fortran dll 和 C dll 上执行了 dumpbin /headers
,这两个透露机器是8664(64位架构)
我在 C 代码的 Fortran dll 函数原型中使用 float** 和 int**,因为我从 C 函数中调用 Fortran 函数,该函数已经将指针作为参数,所以如果我不使用“双指针”调用 Fortran 函数时,我从编译器收到警告。
是的,Fortran 运行时库在环境中,我经常使用 Fortran,我知道这不是问题。
我有一些编译为 dll 对象的 C 代码。
我有一个单独的项目,用 Fortran 编写,我也将其编译为单个 dll 对象。
我需要从 C dll 调用 Fortran dll 中的函数,而不使用 LoadLibrary。我还需要 2 个 dll 保持独立,这样我就可以替换一个或另一个而无需重新编译它们。
我已经阅读了一些关于该主题的信息,但我无法让它发挥作用。编译器不会抛出错误或警告,但是当我启动主程序时它会失败。这是我尝试过的:
我已经用
声明了我希望从 C 代码调用的所有函数BIND ("C", NAME="FUNCNAME")
我在里面声明了
USE, INTRINSIC :: ISO_C_Binding
我打算从 C 代码调用的函数和子例程我在 Fortran 中包含了
!DEC$ ATTRIBUTES DLLEXPORT :: NAME
代码(我正在使用 ifort)我在我的 Fortran 代码中使用了 c 类型的变量
我在C代码中通过引用传递变量
我将 Fortran dll .lib 文件作为源文件包含到 C 项目中
根据我查阅的大多数资料和文档,我应该能够简单地执行以下操作:
在 Fortran 中:
SUBROUTINE FORTRANDLLFUNCTION(arg1, arg2, arg3, char1) BIND (C, NAME='FORTRANDLLFUNCTION')
USE, INTRINSIC :: ISO_C_Binding
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANDLLFUNCTION
REAL(C_FLOAT), INTENT(INOUT) :: arg1
REAL(C_FLOAT), INTENT(INOUT) :: arg2
REAL(C_FLOAT), INTENT(INOUT) :: arg3
CHARACTER(KIND=C_CHAR), INTENT(IN ) :: char1
<do stuff>
END SUBROUTINE FORTRANDLLFUNCTION
在 C:
extern void FORTRANDLLFUNCTION(float**, float**, float**, char*, int);
float a, b, c;
char abc;
FORTRANDLLFUNCTION(&a, &b, &c, abc, sizeof(abc));
但是,运行在主程序中出现错误。如果我删除对 Fortran 函数的调用和 运行 带有已编译 C dll 的主程序,它就可以工作。我的问题的根源是什么?
这是 dumpbin /exports
在已编译的 Fortran dll 上的输出:
这是 dumpbin /imports
在已编译的 C dll 上的结果:
所以我终于找到了问题的原因...
我放弃了这个并专注于项目的不同部分,这让我发现我得到这个错误的原因是 Fortran dll 不必与C dll,但与调用 C dll 的 exe 相同的目录(C dll 位于不同的位置)。
这真的让我感到惊讶,因为我收到的错误是“无法加载 C.dll”,而不是“无法 find/load fortran.dll”,正确的回溯或消息可以节省我几个小时...
无论哪种方式,如果不是@Mgetz 的评论,我相信它无论如何都不会奏效,所以非常感谢,真的!
对问题的一些评论进行更多说明:
在我最终意识到解决方案是什么之前,除了使用 cmake .. -G "Visual Studio 17 2022" -A x64
创建我的 VS 项目之外,我还在 Fortran dll 和 C dll 上执行了 dumpbin /headers
,这两个透露机器是8664(64位架构)
我在 C 代码的 Fortran dll 函数原型中使用 float** 和 int**,因为我从 C 函数中调用 Fortran 函数,该函数已经将指针作为参数,所以如果我不使用“双指针”调用 Fortran 函数时,我从编译器收到警告。
是的,Fortran 运行时库在环境中,我经常使用 Fortran,我知道这不是问题。