VBから文字列をDLLに渡し、その文字列をファイル名にするには?


龍一郎  2004-11-24 21:44:56  No: 86860  IP: [192.*.*.*]

〜話の流れ〜
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200411/04110109.txt

様々にアドバイスを受け、以下のソースのようになりましたが
エラーが出てうまく動いてくれません。

'vb
Private Declare Sub strings Lib "strings.dll" (ByVal filename As String)

Private Sub Command1_Click()
    Call strings(textbox1.Text)
End Sub


//dll
FILE *fp1;
char code[10];
char* filename;

_declspec(dllexport) void _stdcall setFileNameDLL(char* getfilename){
    char s[20];
    strcpy(s,getfilename);
    getfilename=strcat(s,".txt") ;   
    filename = getfilename;
}

void makeFile(){
    fp1=fopen(filename,"a");
    fprintf(fp1,"making file\n");
    fclose(fp1);
}

>メモリ管理の知識があやふやなままコードを組んでしまうのはやめましょう
と言われたのですが、いまいち分かりません…。
どの部分に関してメモリ管理が不行き届きなのでしょうか?

編集 削除
。。。  2004-11-24 21:52:56  No: 86861  IP: [192.*.*.*]

メモリ管理があやふやといったのは

getfilenameでうけたポインタに対して直接strcatをやってたとこです。
上記は修正されているみたいですけど。

>_declspec(dllexport) void _stdcall setFileNameDLL(char* getfilename){
>    filename = getfilename;
>}

>void makeFile(){
>    strcpy(code,".txt");
>    strcat(filename,code);
>    fp1=fopen(filename,"a");
>    fprintf(fp1,"making file\n");
>    fclose(fp1);
>}

ところでmakeFileはどこで使ってるの?

編集 削除
龍一郎  2004-11-24 22:16:41  No: 86862  IP: [192.*.*.*]

makeFileは_declspec(dllexport) void _stdcall setFileNameDLL(char* getfilename)
とは異なるDLL関数内で使っています。
あ、同じDLLファイルの中の異なる関数と言う意味です。

ここの場合VBでsetFileNameDLLを呼び出した直後に
その関数を呼び出してファイルの保存をさせようとしています。

一つ疑問なのは、前のスレッドで書いた↓ですね。( ^ ^ ; )

>つまりsetFileNameDLLを呼び出した瞬間だけfilenameにgetfilenameが代入されていて、
>makefileの実行時にはfilenameにgetfilenameは無いということでしょうか??

>自分としては、すべてのDLLのソースをひとつにまとめているので
>同じDLL内ならば、どこで代入してもDLL実行中は有効だと思っていたのですが…。
>同じDLL内でも関数が違えば有効範囲は各々の関数内部のみだということなのでしょうか?

編集 削除
。。。  2004-11-24 22:27:32  No: 86863  IP: [192.*.*.*]

よく見たらとんでもないことしてますね。
>   strcpy(s,getfilename);
ここでsにコピーしてるのに
>   getfilename=strcat(s,".txt") ;   
ここでgetfilenameのポインタの値を破壊してますよ。

やっぱりメモリ管理について知識がとんでいるようです。
もうちょっと基礎を勉強してから作ることをお勧めします。

編集 削除
龍一郎  2004-11-24 22:36:56  No: 86864  IP: [192.*.*.*]

前のスレでねろさんが、
__declspec(dllexport) void __stdcall strings(char* str)
{
  char s[20];         
  strcpy(s,str);
  str=strcat(s,".txt") ;    
}
とされていたので、例に倣ってみたんですが…。

_declspec(dllexport) void _stdcall setFileNameDLL(char* getfilename){
    char s[20];
    strcpy(s,getfilename);
    filename = strcat(s,".txt") ;   
}
とするべきですかね…。

>やっぱりメモリ管理について知識がとんでいるようです。
>もうちょっと基礎を勉強してから作ることをお勧めします。

ありがとうございます。
自分でも勉強不足なのは重々承知でしたが、
何事もチャレンジと思い、やっています。

編集 削除
。。。  2004-11-24 22:43:27  No: 86865  IP: [192.*.*.*]

じゃなくてs[20]はスタック上にとっているメモリだから
setFileNameを抜けると開放されちゃうんですよ。
そのポインタを参照するとどうなるか分かりますよね。

編集 削除
36NET  2004-11-25 09:50:09  No: 86866  IP: [192.*.*.*]

プログラムってVBから初めてしまうとCのポインタの概念って結構理解に苦しみますよね
そもそもs[20]を使う必要がないと思うんですが?

http://homepage2.nifty.com/DSS/VCPP/DLL/dllindex.htm
ちょっと古いですが↑昔だいぶ参考にしました

testdll.c

#include <stdio.h>
#include <windows.h>

int WINAPI test1(const LPCSTR chRead);
int WINAPI test2();

char chfname[_MAX_PATH];

BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    return(TRUE);
}

/* API */
int WINAPI test1(const LPCSTR chRead)
{
  sprintf(chfname, "%s.txt", chRead);

  return(0);
}

int WINAPI test2()
{
  FILE *fp;

  fp = fopen(chfname, "a");
  fprintf(fp, "making file\n");
  fclose(fp);

  return(0);
}

testdll.def

LIBRARY testdll
EXPORTS test1
EXPORTS test2

VB

Option Explicit

Private Declare Function test1 Lib "testdll.dll" (ByVal chRead As String) As Long
Private Declare Function test2 Lib "testdll.dll" () As Long

Sub Main()

    Call test1("test")
    Call test2

End Sub

編集 削除
ペソ23  2004-11-25 10:42:10  No: 86867  IP: [192.*.*.*]

http://homepage2.nifty.com/DSS/VCPP/DLL/dllfilefp.htm
つまり、↑コレじゃないのか?

編集 削除
 2004-11-25 16:29:42  No: 86868  IP: [192.*.*.*]

>つまり、↑コレじゃないのか?
いや違うだろうと考えるが…
>void makeFile(){
>    fp1=fopen(filename,"a");
>    fprintf(fp1,"making file\n");
>    fclose(fp1);
>}
fp1はmakeFile内部のauto変数だし、閉じてるからVBでは使わないと思われ。

あとだな、龍一郎さんの考えているCのポインタはどうも「メモリバッファをコピーして受け渡している」と誤解しているようだが、
そんな無駄なことは「できない」と思われ、所詮ポインタは先頭メモリアドレスだ。
あと、微妙に変数のスコープの概念も怪しいと考えられる。

編集 削除
ねろ  2004-11-25 17:59:13  No: 86869  IP: [192.*.*.*]

難しく考えずに「。。。」さんが言われるように単に
char s[255];
_declspec(dllexport) void _stdcall setFileNameDLL(char* getfilename){
    strcpy(s,getfilename);
    strcat(s,".txt") ;   
}
_declspec(dllexport) void _stdcall makeFile(){
    FILE *fp1;
    fp1=fopen(s,"a");
    fprintf(fp1,"making file\n");
    fclose(fp1);
}
でいいんでは。
長いファイルネームが入って来てもいいようにsは長く取っておいた方がいいかも。

編集 削除