2013-04-27 12 views
0

C# 콘솔 응용 프로그램에서 Fortran DLL에 저장된 서브 루틴을 호출 할 때 다음 오류가 계속 발생합니다. "처리되지 않은 'System.EntryPointNotFoundException'형식의 예외가 이름에 발생했습니다. exe 추가 정보 : 'Fortran.dll'에서 'Fortran_Subroutine'이라는 항목을 찾을 수 없습니다. "이 오류 메시지와 관련된 거의 모든 게시물은 C#/C++와 관련이 있습니다. Fortran 프로젝트에는 DLL을 C# 프로젝트 (CSharp_proj \ bin \ debug)로 복사하는 빌드 후 이벤트가 있습니다.C#/Fortran : 진입 점을 찾을 수 없습니다.

포트란 코드에 두 통화를 사용! 감속 $을 수행 그들은? OK 보면

C 
    MODULE MF_DLL 
C 
    CONTAINS 
C 
    SUBROUTINE MFNWT_INIT() 
C  
    !DEC$ ATTRIBUTES DLLEXPORT :: MFNWT_INIT 
    !DEC$ ATTRIBUTES DECORATE, ALIAS: "MFNWT_INIT" 
C 
    USE GLOBAL 
    ...(do stuff) 

    RETURN 
    END SUBROUTINE MFNWT_INIT 

포트란을 호출하는 C# 코드, 않는 같이 DllImport 호출 모습 OK?

using System.Runtime.InteropServices; 

public static class CustomMODSIM 
{ 
    public static Model myModel = new Model(); 
    private static SortedList myStreamNodes; 

    public static void Main(string[] CmdArgs) 
    { 
     string FileName = CmdArgs[0]; 
     myModel.Init += OnInitialize; 
     ...(do more stuff)... 

     //Function call that will invoke "OnInitialize" below 
     myProgram.RunSolver(myModel); 
    } 

    private static void OnInitialize() 
    { 
     //call Fortran function 
     MFNWT_INIT(); 

     //Initialize list of stream nodes 
     myStreamNodes = new SortedList(); 
     Node m_Node = myModel.FindNode("NonStorage1"); 
     ...(do more stuff) 
    } 

    //Fortran DLL interface 
    [DllImport("MF_DLL.dll", CallingConvention=CallingConvention.Cdecl)] 
    public static extern void MFNWT_INIT(); 
} 
+0

* " 'Fortran.dll'에서 'Fortran_Subroutine'이라는 엔트리 포인트를 찾을 수 없습니다. 분명히 " 'MFNWT_INIT'... '라는 엔트리 포인트를 찾을 수 없습니까? –

+0

필자는 예제 메시지에서 일반적인 이름을 사용했을 정도로 다양한 조합을 시도해 왔습니다. 내가 지적한 것처럼 특정 코드에 대한 오류 메시지는 "DLL MF_DLL.dll에서 'MFNWT_INIT'라는 항목 포인트를 찾을 수 없습니다" – user2256085

+0

'dumpbin의 결과를 게시 할 수 있다면 도움이 될 것입니다/export MF_DLL.dll'. – user7116

답변

1

두 번째 컴파일러 지시문 (두 번째! DEC $ 행)이 올바르지 않습니다. 즉, 지정된 포트란에 지정 속성 (DECORATE 및 ALIAS)이 지정되어있는 :: MFNWT_INIT 부분이 누락되었습니다. 나는 컴파일러가 구문 문제에 대한 경고를 내기를 기대한다.

ifort> = 11 또는 그 조상 중 하나가 아닌 버전을 사용한다고 가정 할 때 : C 호출 규칙을 사용하려면 두 번째 지시어를 제거하는 것이 좋습니다 SUBROUTINE 문에서 접미어 BIND(C,NAME="MFNWT_INIT") 만 사용하면됩니다.

+0

컴파일러 옵션에 대한 BIND 수정 자나 변경 사항이 없으면 심볼 끝에 밑줄이 기본값이라고 생각합니다. – user7116

+0

DEC $ 줄의 코드를 수정하고 Fortran 서브 루틴을 수정했습니다. like : "SUBROUTINE MFNWT_INIT() BIND (C, NAME ="MFNWT_INIT ")"그랬어! – user2256085

+0

나는 이 게시물이 도움이 될 것입니다. C# 코드 줄을 다음과 같이 변경했습니다. [DllImport ("MF_DLL.dll", CallingConvention = CallingConvention. ** StdCall **)] – user2256085

1

DLL이 데코 레이팅 된 이름을 사용하여 함수를 내보낼 가능성이 큽니다. 그 이름이 무엇인지 찾아서 C# 측에서 사용하십시오.

[DllImport("MF_DLL.dll", CallingConvention=CallingConvention.Cdecl, 
    EntryPoint="DecoratedNameGoesHere")] 
public static extern void MFNWT_INIT(); 

내 보낸 이름을 찾으려면 dumpbin 또는 Dependency Walker와 같은 도구를 사용하십시오.

DLL에서 cdecl 호출 규칙을 사용하고 있습니까?

+0

그것은 대부분'MFNWT_INIT_' 또는'됩니다 대부분의 기본 컴파일러 옵션을 사용하는 _MFNWT_INIT' – user7116

+0

@six 질문 : 요점은 문제를 진단하는 방법을 묻는 것입니다. –

+0

많은 포트란 컴파일러에서 사용 된 후행하는'_'을 지적하고 있습니다. if if – user7116

0

IVF 도움말에서 혼합 언어로 프로그래밍/혼합 언어/특성 속성 및 호출 규칙에서 호출 규칙 조정을 살펴보십시오. 그것이 버전 11에있는 곳입니다. 사용중인 버전으로 옮겼을 수 있습니다. 도움말의 혼란스러운 부분은 내 보낸 기호가 대문자인지 아니면 소문자인지 여부입니다. 이것은 이전 MS Fortran 77 컴파일러 (1986 년경) 용으로 작성된 것과 약간 다릅니다. 내 보낸 기호가 확실하지 않은 경우 depends을 사용하여 기호가 무엇인지 확인하십시오.

1) 별칭을 사용하지 않는 경우, 다음은 포트란 측에이 같은

MODULE MF_DLL 
CONTAINS 
SUBROUTINE MFNWT_INIT() 
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: MFNWT_INIT 

STDCALL를 사용하는 경우가있을 것입니다이 개 보낸 문자 표시되어야합니다 MF_DLL_mp_MFNWT_INIT 및 _MF_DLL_mp_MFNWT_INIT 0 @. STDCALL을 지정하지 않으면 기본적으로 C로 설정됩니다.이 경우에는 MF_DLL_mp_MFNWT_INIT 만 사용됩니다. @ 기호 뒤의 숫자는 호출자에게 리턴하기 전에 루틴이 제거해야하는 스택의 바이트 수입니다. 호출자의 책임이기 때문에 C decl에서이 값을 얻지 못합니다. CDECL

[DllImport("MF_DLL.dll", CallingConvention=CallingConvention.Cdecl, 
EntryPoint="MF_DLL_mp_MFNWT_INIT")] 
public static extern void MFNWT_INIT(); 

차이를 이용하여 C# 1 측)

[DllImport("MF_DLL.dll", CallingConvention=CallingConvention.StdCall, 
EntryPoint="[email protected]")] 
public static extern void MFNWT_INIT(); 

3 stdcall을 사용하는 C# 1 측에

2) C에서는, 그 수를 알 필요가 없다는 것이다 반면 stdcall에서는 매개 변수를 사용합니다.이는 매개 변수의 스택/언 스택에 영향을줍니다. 이것이 잘못되면, 전화를 걸고 Fortran 루틴을 실행 한 다음 종료시 충돌합니다. 귀하의 경우에는 매개 변수가 없기 때문에 문제가되지 않지만 올바르게 가져 오는 것이 좋습니다.

4) 별칭이 사용되면 이름은 변경되지만 호출 규칙은 변경되지 않습니다. 귀하의 경우에는 지정해야합니다

!            ,-- This is the name in DLL export 
!DEC$ ATTRIBUTES DECORATE, ALIAS: "MFNWT_INIT"::MFNWT_INIT 

C decl을 사용하면 MFNWT_INIT가 표시됩니다. STDCALL을 사용하면 MFNWT_INIT 및 _MFNWT_INIT @ 0 을 얻을 수 있습니다. C# 측에서 C Decl을 사용할 때 엔트리 포인트가 필요하지 않습니다. STDCALL이 사용될 때만 필요합니다.

5) 루틴이 Fortran과 C#에서 모두 사용되는 경우 stdcall을 사용하는 것이 좋습니다.

관련 문제