質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

F#

F#は、MicroSoftが開発した.NET Framework 向けのマルチパラダイムプログラミング言語です。 Visual Studio 2010 より標準搭載されました。

Q&A

解決済

1回答

548閲覧

C++のプログラムからF#の関数の呼び出し方

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

F#

F#は、MicroSoftが開発した.NET Framework 向けのマルチパラダイムプログラミング言語です。 Visual Studio 2010 より標準搭載されました。

0グッド

1クリップ

投稿2017/09/29 07:08

###前提・実現したいこと
C++のプログラムからF#の関数を呼び出したいです。

###発生している問題・エラーメッセージ
C++のプログラムでF#の関数を呼び出したいのですが,やり方が分かりません。

###該当のソースコード

ここにご自身が実行したソースコードを書いてください

###試したこと
F# のソースファイルで関数の宣言部分でextern "F" や__declspec(dllexport)を、
C++で[<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]を記述してみましたがダメでした。

###補足情報(言語/FW/ツール等のバージョンなど)
開発環境:Visual Studio 2013 Update4
F# 3.1
フレームワーク:.Net Framework 4.5.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2017/09/29 14:12

"C++"というのはunmanagedなnative C++を指していますか?もしくは.NET C++/CLIですか?
退会済みユーザー

退会済みユーザー

2017/10/02 01:03

.Net C++/CLI(visual C++)を使っています。曖昧な部分があり、すみません。
guest

回答1

0

ベストアンサー

C++からF#の関数を呼ぶのは不可能ではないはずですが、現状、かなり難しいようです。

お試しになったやり方は F#からC++/C言語の関数を呼ぶP/Invokeの方法です。
(ただし、それでも不完全です)目的の再確認になりますが、呼び出す側の言語としては
.NET Framework用のC++/CLIではなく、ネイティブのC++ からF#の関数を呼ぶ方法、
で正しいでしょうか。

F# はご存知のように、.NET Framework上で稼動する実行ファイルを作成する言語です。
C++で作成したネイティブの実行コードからは、.NET Framework上で動作するコードに
アクセスする為、.NET Frameworkとは別の、WindowsのCOMインターフェースを
経由する必要があります。

以下は、「C++からC#のDLLを呼ぶ方法」を紹介された、大変参考になる情報へのリンクです。
C++からC#のDLLを呼ぶ方法

大筋においてこちらで紹介されている方法でC#のコード、ひいては.NET Framework用の
言語で提供される関数に、全部とはいかず、制限付きながらもアクセスできるはずですが、
Visual Studio 2015(※1)でのF#のプロジェクトの設定画面をみると、ビルドで造られる
アセンブリDLLを「COMの相互参照を可能」とし、Windowsに登録する方法が見当たりませんでした。

別途コマンドラインからセットする方法もありそうなのですが、正しく動作する例は未確認です。
※1 質問者様の使われているVisual Studioは2013ですが、ほぼ同じと思われます。

現状、F#の関数を別のC++な言語から利用する手としてより簡単なのは
0. F#の関数を C++ではなく、C++/CLIから利用する。

  1. F#の関数を C#から利用する。C#とC++はCOMを経由して使う。

かと考えられます。ソフトの規模にもよりますが、そうまで苦労してネイティブ用C++
からF#の関数を呼べるようにするべきか、再考の余地があるかと思います。

尚、上記とは反対にF#からC++の関数を呼ぶのは正しくP/Invoke 用の設定さえすれば、はるかに簡単です。

参考になれば幸いです。

[追記] C++/CLIのコードから F#のものを呼び出す

Visual Studio 2012でできました

前提がC++/CLI と言うことでしたので、改めて確認しました。
遅くなりましたが、試して確証を得た範囲でお答えします。

私の方で先に提示させていただいた代案

  1. F#の関数を C++ではなく、C++/CLIから利用する。

ですが、Visual Studio のバージョンによってはビルドできず、確認できませんでした。
OKだったのは Visual Studio 2012 ですので、そちらで紹介します。
VS2015ではNGでしたが、いろいろいじって環境が変わったせいがあるかもしれません。
(原因は追究できていません)
VS2013はインストールしていないので未確認です。

VS2012で試した限り、基本的には以下のプロジェクト作成の流れで
C++/CLIからF#のメソッドを呼べました。

  1. F#のプロジェクトを「ライブラリ」で作成する。(.NETアセンブリ DLL)
  2. 同じソリューションの管理下で、C+++/CLIのプロジェクトを作る。

 (「コンソールアプリ」で試しました)
2. C++/CLIのプロジェクトの「参照」で、F#のプロジェクト自体を参照させる。
※Visual StudioS2015 ではエラーが発生し、できませんでした。

  1. F# のコードを書く。

例を示します。デフォルトコンストラクタと、intとstring を返すメソッドを持つ簡単なクラスです。

F#

1namespace LibrarySpace 2 3type FSharpLibrary = class 4 val intA: int 5 val stringA: string 6 7 (* default constructor *) 8 new () = { 9 intA = 10 10 stringA = "String#10" 11 } 12 13 (* return in *) 14 member this.getIntA = this.intA 15 16 (* return string *) 17 member this.getStringA = this.stringA 18 19 end;;

5.C++/CLIのコードを書く。コンソールアプリです。このコードでF#の
"LibrarySpace"名前空間のFSharpLibraryクラスのインスタンスへアクセスします。

// C++/CLI #include "stdafx.h" #include <vcclr.h> // PtrToStringChars() #include <stdio.h> // wprintf() using namespace System; using namespace LibrarySpace; int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello"); FSharpLibrary^ lib = gcnew FSharpLibrary(); // getIntAメソッド呼び出し int num = lib->getIntA; // getStringA メソッド呼び出し System::String^ s = lib->getStringA; Console::WriteLine(s); // Cランタイムで文字列を表示 wchar_t* ps = (wchar_t*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(s).ToPointer(); wprintf(L"printf: %s\n", ps); System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(ps)); Console::WriteLine(L"End"); return 0; }

これで、F#のLibrarySpace::FSharpLibraryクラスのgetIntA, getStringAメソッドを
呼び出せることを確認できました。名前空間(例では"LibrarySpace")に注意してください。
正しく参照できていれば、Visual Studioのインテリセンスで自動的にシンボルが
入力できるようになります。

例のコードで分かるように、C++/CLI側のコードでは、例えばchar* やwchar_t 等の
ネイティブの文字列を扱うときには .NET Framework のSystem::Stringとchar* 等を
相互変換する必要があります。面倒くさいので、適切なラッパー関数を更に書く必要が
あるかもしれません。

また、上記のテストプロ含め、F#<-->C++/CLI間での簡単なやり取りしか確認していません。
F#でのタプル等の複雑な入出力が扱えるかは未確認です。

投稿2017/10/01 15:56

編集2017/10/03 08:10
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/10/02 01:11

ご回答ありがとうございます。 お忙しい中で大変丁寧にお答えいただいたところ恐縮ですが、呼び出す側の言語はC++/CLI(visual C++)になります。 C++/CLI(visual C++)からの呼び出し方も教えていただけないでしょうか。 自分の質問の書き方が不正確なばかりに申し訳ございません。
dodox86

2017/10/03 08:11

Visual Studio 2012 のC++/CLI, F#で確認したものを追記しました。
退会済みユーザー

退会済みユーザー

2017/10/03 08:13

たいへん丁寧なご回答ありがとうございます。 Visual Studio2013でやってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問