開発環境;VC++.NET,VB.NET
受け取ったパスよりテキストファイルを読出し、
その文字列を返す関数を実装したVC++.NETのDLLを作成しました。
VB.NETで作成した実行ファイルより、このDLLを呼び出しているのですが
文字化けした文字列が帰ってきてしまいます。
以下DLLソース
#include <fstream>
#include <istream>
#include <vector>
#include <string>
using namespace std ;
<中略(エントリーポイント)>
const char* _stdcall readText(const char* filename)
{
std::ifstream fin(filename) ;
if(!fin.is_open()) return "" ;
std::string s ;
while(std::getline(fin, s)) ;
return s.c_str() ;
}
デバッグしてみたところ、やはりsには意図したものでない値が
格納されていました。
どうやら文字列を取得する場合の戻り値の型の指定が良くわかってない
ようなのですが、どなたかソースの修正を教えて頂けませんでしょうか。
よろしくお願い致します。
std::stringについて詳しく知らないのですが、
この提示された関数を抜けると、std::string s;のスコープを抜け、
この関数をコールした側に制御が戻ったときには、sの有効期間(?)が過ぎており、
sは存在していないのではないでしょうか?
で、存在していないオブジェクトへのポインタを受け取っても、全くダメだと思いますが。
関数のコール元で、格納領域を確保し、その領域アドレスを関数に引数としてわたし、
関数内では、その受け取ったアドレスの領域にデータ(文字列)を格納するという手法が、
一般的ではないでしょうか。
#識者の方々、フォローをお願いします。
DLLとEXE側とでメモリ空間が違うから、ポインタを渡しても無意味のような。。
EXE側で領域確保したバッファを渡して処理を行なうか、
DLL側でメモリを確保し、DLL側でメモリを開放するよう設計し、EXE側で最後に
DLL側のメモリ開放関数を呼ぶ。
> DLLとEXE側とでメモリ空間が違うから、ポインタを渡しても
> 無意味のような。。
アクセスできるメモリ空間自体は一緒なはずです。
ランタイムライブラリやクラスの実装などの差異による
メモリ配置や扱い方が違うので、それを吸収するために上記対応をする。
#揚げ足を取るようで申し訳ありませんが
> ランタイムライブラリやクラスの実装などの差異による
> メモリ配置や扱い方が違うので、それを吸収するために上記対応をする。
std::string そのものを戻り値として返すならばそう言えますが、
const char * を返す限りにおいて、そのような差異はありません。
> 関数を抜けると、std::string s;のスコープを抜け、
> この関数をコールした側に制御が戻ったときには、sの有効期間(?)が過ぎており、
> sは存在していないのではないでしょうか?
対応はこのためでしょう。
シャノン様、
ご指摘感謝します。s でなく s.c_str() でしたか。
DLLは直接関係してないこととKING・王様の説明を今さら理解しました。
RAPT様にも的外れな突っ込みで申し訳なかったです。
関係しうるのは下記だけなので他は読み飛ばしてください。
>アクセスできるメモリ空間自体は一緒なはずです。
KING・王さん、RAPTさん、nonameさん、シャノンさん。
回答どうもありがとうございます。
文字列を返すことは容易にできるのですが、読み込んだテキストファイルの
内容を返すことがまだできていません。その辺りはもう少し調べてみようと
思います。
ツイート | ![]() |