VC++でDLLを作成しています。
VBから呼び出しで、配列を渡し、その配列の値を
VCで使用したいのです。
通常変数でテストして、うまくいっているのですが、
配列に変更したところ、値がうまく渡りません。
どなたかお分かりになられる方いらっしゃいましたら
お力をお貸し願えないでしょうか?
変数で成功しているプログラム
VB6.0
標準モジュール
Declare Function fncTest Lib "fncTest.dll" (a As Long) As Long
フォーム
Private Sub Test_Click()
dim i as integer
i = fncTest(1)
End Sub

VC++6.0
fncTest.h
fncTest_API int _stdcall fncTest(int);
fncTest.cpp
fncTest_API int _stdcall fncTest(int a)
{
a = a+1;
return a;
}
fncTest.def
    省略
変数aを配列に変更して作ってみたもの(配列bにVBからの配列aの値を入れようとしていますが、
うまくいっていません。)
VB6.0
標準モジュール
Declare Function fncTest Lib "fncTest.dll" (ByRef a() As Long) As Long
フォーム
Private Sub Test_Click()
Dim i As Integer
Dim hairetu(7) As Long
Dim values As Variant
For i = 0 To 7
hairetu(i) = i
Next i
values = fncTest(hairetu())
End Sub

VC++6.0
fncTest.h
fncTest_API int _stdcall fncTest(int*);
fncTest.cpp
fncTest_API int _stdcall fncTest(int* a)
{
int b[7];
int i;
for (i = 0;i <= 7;i++){
b[i] = a[i];
}
return 0;
}

以上よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

VBの配列は管理領域などを含んでいますので、


そのままではうまく渡りません。
配列の先頭要素を参照渡しするとうまくいくと
思います。この場合、当然ですがC側では配列の
範囲を知ることが出来ませんので、その辺は引数で
管理してください。
ちなみに、ユーザ定義型の配列は各要素がメモリ内で
連続してないようなので、ユーザ定義型の場合は
ご注意ください。

Declare Function fncTest Lib "fncTest.dll" (ByRef a As Long, ByVal n As Long) As Long
フォーム
Private Sub Test_Click()
Dim i As Integer
Dim hairetu(7) As Long
Dim values As Variant
For i = 0 To 7
hairetu(i) = i
Next i
values = fncTest(hairetu(0), 8)
End Sub

VC++6.0
fncTest.h
fncTest_API int _stdcall fncTest(int*, int);

fncTest.cpp
fncTest_API int _stdcall fncTest(int* a, int n)
{
int sum;
int i;
for (i = 0; i < n; i++){
sum = a[i];
}
return 0;
}

この回答への補足

VB側のDim values as variant
values = fncTest(hairetu(0),8)
の部分の戻り値はMSDNのサンプルを参考にして書きました。
まったく意味がないことがわかったので
Dim values as integer
values = fncTest(hairetu(0),8)
で単純に戻り値を受け取るということでよかったと思います。
今後これを参考になされる方が混乱しないように
補足しておきますね。

補足日時:2005/04/12 11:04
    • good
    • 0
この回答へのお礼

どうもありがとうございました(^^)。
hairetu(0)を渡すことによって無事VCに値が渡りました。
なんとお礼をいえばいいのかわからないくらい
感謝感激です。
本当にありがとうございました
m( _ _ )m

お礼日時:2005/04/12 11:04

すいません。

sumの初期化を忘れてました。
C側の
int sum;

int sum = 0;
に置き換えてください。
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVBのFunctionで、配列を引数や返却値にできますか?

配列の要素をソートするFunction を作成しようとしているのですが、
ソート対象配列を引数にして、返却値がソートされた配列になるように
したいと思ったのですが、その方法がわかりません。
それとも、引数に配列を入れることは不可能なのでしょうか。

Aベストアンサー

こんな感じです。配列をクイックソートしています。
配列を引数にするには、
Function hoge( Array()) As Long

End Function
のようにします

VBでは通常は「参照渡し」で引数を渡しますので、hoge()中でArray()の内容を書き換えると、呼び出しもとの関数中でも書き換え後の値を使用することが出来ます。

下記で、「ByRef Values()」としているのは、明示的に参照渡しである事を指定することにより、これを読むプログラマに対して「呼び出すとココの値を変更するねんで」ってことを伝えているわけです。



Option Explicit

Sub Main()
  Dim i As Long
  Dim Values() As Long
  
  '配列を初期化する
  ReDim Values(255) As Long
  For i = 0 To 255
    Values(i) = Rnd * 256
  Next i
  
  '配列をソートする
  Call QuickSortLong(Values())
End Sub

Public Sub QuickSortLong(ByRef Values() As Long, Optional StPos As Long, Optional EdPos As Long)

  Dim Ct As Long    'カウンタ
  Dim LastPos As Long  '配列最終番号
  Dim Buffer As Long   'バッファ
  
  '引数省略時の初期値
  If IsMissing(StPos) Then
    StPos = LBound(Values, 1)
  End If
  If IsMissing(EdPos) Then
    StPos = UBound(Values, 1)
  End If

  '終了番号が開始番号以下のときは処理を行わない
  If StPos >= EdPos Then
    Exit Sub
  End If

  '最初の値をバッファに格納
  Buffer = Values(StPos)
  '各バッファの値をスワップする
  '真ん中にある配列の値を最初の配列に代入する
  Values(StPos) = Values((StPos + EdPos) / 2)
  'バッファに格納された値を真ん中の配列に代入する
  Values((StPos + EdPos) / 2) = Buffer

  LastPos = StPos

  For Ct = StPos + 1 To EdPos
    If Values(Ct) < Values(StPos) Then
      LastPos = LastPos + 1
      '各バッファの値をスワップ
      Buffer = Values(LastPos)
      Values(LastPos) = Values(Ct)
      Values(Ct) = Buffer
    End If
  Next Ct

  '各バッファの値をスワップ
  Buffer = Values(StPos)
  Values(StPos) = Values(LastPos)
  Values(LastPos) = Buffer
  
  '再起呼び出し
  Call QuickSortLong(Values, StPos, LastPos - 1)
  Call QuickSortLong(Values, LastPos + 1, EdPos)
End Sub

こんな感じです。配列をクイックソートしています。
配列を引数にするには、
Function hoge( Array()) As Long

End Function
のようにします

VBでは通常は「参照渡し」で引数を渡しますので、hoge()中でArray()の内容を書き換えると、呼び出しもとの関数中でも書き換え後の値を使用することが出来ます。

下記で、「ByRef Values()」としているのは、明示的に参照渡しである事を指定することにより、これを読むプログラマに対して「呼び出すとココの値を変更するねんで」ってことを伝えているわけです...続きを読む

Qfor(int i = 100, long n = 1; i > n/3i; i++)

for(int i = 100, long n = 1; i > n/3i; i++)
のように、初期設定で型の違う変数を宣言したいんだけど
C++ではこんなふうに2つ以上の型を宣言してはいけないんですか?

Aベストアンサー

,

コンマ演算子の原理です。
forの初期化文で "," で区切れるのは値を返す文だけです。
よってintステートメントもlongステートメントも値を返さないので、この文では使用できません。

というか、むしろ、intステートメントの第2引数としてlongが認識されてしまいます。
外で

int i; long n;

とし

for(i = 0, n = 0; hoge; hoge)

なら可能です。

QVB.NET: 型が配列のときの戻り値は?

仮に戻す値が無い場合は、私は Nothing かなと思います。
しかし、プログラマでもない素人。
VB.NET の学習も一カ月未満の超初学者。
もっとも、基本的なこととは思いますが答えが知りたいです。

「そうじゃない!ByRef を使う方が望ましい!」

という考え方もありかな!とも思っています。

Aベストアンサー

Functionの話ですね。
たった一つの答えというものはおそらく無くて、その戻り値を受け取る側でどうしているか、に影響されてくるのではないでしょうか。

例えば、そのメソッドの処理内でOKパターンではないと判別したとき、Nothingを返すことにより、待ち受ける側でNothingかどうかにより以後の処理を振り分けることが出来ます。
ただ、この場合は空の配列を返してもいいかもしれません。

もちろん、値を返さない場合があるという状況を作りたくないのであれば、FunctionではなくSubとして、ByRefの引数を使うという手もなくはないかも知れません。
この場合、事前に引数として用意しておかなければなりませんが。

大事なことかなと思うので2回言いますが、結局は「どうしたいか」が答えを決めると思います。

Qint i,j; \n i=0,j=5;

int i,j;
i=0;
j=5:
と書いてあるソースは普通ですが、
int i,j;
i=0,j=5:
と書いてあるソースもあります。
後者はC++の正しい書式ですか?

カンマ演算子というのは後者のカンマのことですか?

Aベストアンサー

 正しい書式です。

i=0,j=5;
 における、「,」をカンマ演算子といいます。2項の演算子です。カンマで区切られた演算を「左から順番に」実行し、最後の演算を結果として返します。
 したがって、例の文であれば、i=0を実行し、次にj=5を実行。そして、j=5の結果の5を結果として返します。
 ・・・
 が、本来的には、あまり、例のような使い方はしませんね。よく見られるのは、次のような場合です。

 for (i=0,j=0 ; i < 50 ; ++i,++j) {

 のような形でよく見られます。for文の各式は、一つの式でなければならないので、こんな書き方をするわけです。初期化と更新部が一つにまとまり、ループが読みやすくなるのが利点かな。

QArrayListの初期値に二次元配列を設定したい(VB2005)

下記は、aryhogeにTextBoxオブジェクトを格納する処理です。

----------------------------------------
'a)
Dim hoge()() As TextBox = _
      {New TextBox() {txta01, txtb01, txtc01}, _
      New TextBox() {txta02, txtb02, txtc02}, _
      New TextBox() {txta03, txtb03, txtc03}}

Dim aryhoge As New ArrayList    'b)

aryhoge.Add(hoge(0))
aryhoge.Add(hoge(1))
aryhoge.Add(hoge(2))
----------------------------------------

(a)を(b)の初期値として設定するにはどのようにすればよいか、ということが質問内容です。

試しに(b)の部分を以下のようにしてみましたが、「1次元配列の値を変換できない」とのエラーが出ました。
Dim aryhoge As New ArrayList(New TextBox() {hoge(0), hoge(1), hoge(2)})

どうぞよろしくお願い致します。

下記は、aryhogeにTextBoxオブジェクトを格納する処理です。

----------------------------------------
'a)
Dim hoge()() As TextBox = _
      {New TextBox() {txta01, txtb01, txtc01}, _
      New TextBox() {txta02, txtb02, txtc02}, _
      New TextBox() {txta03, txtb03, txtc03}}

Dim aryhoge As New ArrayList    'b)

aryhoge.Add(hoge(0))
aryhoge.Add(hoge(1))
aryhoge.Add(hoge(2))
----------------------------------------

(a)を(b)の初期値として...続きを読む

Aベストアンサー

Dim aryhoge As New ArrayList(hoge)

Qint kosuu; とstruct tanka_kosuu kosuu[10]; の関係は

同プログラムの内容で現在3個の質問をしておりますが!
 その質問を解決する上で4つ目の質問をさせていただきます。
 悪しからず・・・
 さて
以下のサイトのプログラムで 些細な疑問がございます。
https://oshiete.goo.ne.jp/qa/9062058.html
 で
 struct tanka_kosuu {
int tanka; 
int kosuu; 
int kingaku; /
以上の中にあるkosuuと
 struct tanka_kosuu kosuu[10];のkosuu[10]とは直接関係がありますか?
 馬鹿な質問ばかりで申し訳ございませんがよろしくお願いいたします。

Aベストアンサー

#No.1です。

>kosuu[10];をakb[10];変えたところ 以下の errorでてコンパイルできません!?
> example10.c(15) : error C2065: 'kosuu' : 定義されていない識別子です。


宣言している変数名を変更したら、その変数を利用している場所(エラーメッセージで15行目と書かれています)の変数名も変更する必要があると思いませんか?

下の例で、1行目も変数をaからbに変えたら、2行目,3行目のaも、bに変える必要があのはご理解いただけますよね?
01: int a;
02: a = 10;
03: printf("a=%d\n", a);

QVB6でやると構造体の配列になる変数をVB2008では何で作ればいいか

VB6でプログラムを作っていたときは
値のセットが配列になるとき
構造体を動的配列で宣言してデータを足して作りました。

VB2008で開発をすることになり
同じようなことをしたいのですが
もっと便利なやり方が登場したりするのでしょうか?
クラスで挑戦したのですが動的配列はできないようでした。

Aベストアンサー

#書き連ねてたらやたら長くなってしまったので必要と思うところだけ抜粋して読んでくださいませ。

> できれば下記のようにしたかったので
> 同じようなことができないでしょうか?

■構造体+配列
Public Structure MainGroup
  Public ID As Integer
  Public SubGroups As SubGroup()
End Structure

Public Structure SubGroup
  Public ID As Integer
  Public Value1 As Integer
  Public Value2 As Integer
  Public Sub New(ByVal ID As Integer, ByVal Value1 As Integer, ByVal Value2 As Integer)
    Me.ID = ID : Me.Value1 = Value1 : Me.Value2 = Value2
  End Sub
End Structure

Public Class Program
  Public Shared Sub Main()
    Dim DataArray As MainGroup() = {}
    Array.Resize(DataArray, 3)

    With DataArray(0)
      .ID = 1
      Array.Resize(.SubGroups, 4)
      .SubGroups(0) = New SubGroup(101, 123, 456)
      .SubGroups(1) = New SubGroup(102, 234, 567)
      ' (略)
    End With

    With DataArray(1)
      ' (略)
    End With
  End Sub
End Class

■クラス+コレクション
Public Class MainGroup
  Public ID As Integer
  Public SubGroup As New System.Collections.Generic.List(Of SubGroup)
End Class

Public Class SubGroup
  Public ID As Integer
  Public Value1 As Integer
  Public Value2 As Integer
  Public Sub New(ByVal ID As Integer, ByVal Value1 As Integer, ByVal Value2 As Integer)
    Me.ID = ID : Me.Value1 = Value1 : Me.Value2 = Value2
  End Sub
End Class

Public Class Program
  Public Shared Sub Main()
    Dim DataList As New System.Collections.Generic.List(Of MainGroup)
    Dim NewMain As MainGroup

    NewMain = New MainGroup
    NewMain.ID = 1
    NewMain.SubGroup.Add(New SubGroup(101, 123, 456))
    NewMain.SubGroup.Add(New SubGroup(102, 234, 567))
    ' (略)
    DataList.Add(NewMain)
  End Sub
End Class

配列+クラスはNULL参照を発生させる可能性がある点で相性がよくありません。コレクション+構造体は、#2で挙げたようにデータ書き換えの手間がかかり、やはり相性はよくありません。
配列は要素数の変動に対してパフォーマンスが悪く、細かく増減させるには不向きです。コレクションは増減することを前提としている点や、削除した箇所を詰めたり途中に挿入したりが容易な点で優れています。
クラス or 構造体、配列 or コレクション をどう組み合わせるかはこれらのほか、ユーザビリティ・保守性・整合性・パフォーマンスなどと共に天秤にかけることになるでしょう。状況にあわせてうまく使い分けてください。


> addでどんどん追加して全体をループさせずに小項目IDを取得する方法

小項目IDがユニークであれば、リストコレクションではなく辞書コレクションを使うことでIDからクラスを取得できるようになります。クラスが保持しているデータをキーに使う場合は、コレクションを継承したクラスを作り、AddをShadowsで置き換えたほうがコーディングミスを防ぐことが出来ます。

■クラス+コレクションクラス
Public Class Group
  Public MainID As Integer
  Public SubID As Integer
  Public Value1 As Integer
  Public Value2 As Integer
End Class

Public Class GroupCollection : Inherits System.Collections.Generic.Dictionary(Of Integer, Group)
  Public Shadows Sub Add(ByVal Item As Group)
    MyBase.Add(Item.SubID, Item)
  End Sub
End Class

Public Class Program
  Public Shared Sub Main()
    Dim DataDict As New GroupCollection
    Dim NewGroup As New Group
    NewGroup.MainID = 1
    NewGroup.SubID = 101
    NewGroup.Value1 = 123
    NewGroup.Value2 = 234

    DataDict.Add(NewGroup)

    Console.WriteLine(DataDict.Item(101).Value2) ' 出力 234
  End Sub
End Class

#書き連ねてたらやたら長くなってしまったので必要と思うところだけ抜粋して読んでくださいませ。

> できれば下記のようにしたかったので
> 同じようなことができないでしょうか?

■構造体+配列
Public Structure MainGroup
  Public ID As Integer
  Public SubGroups As SubGroup()
End Structure

Public Structure SubGroup
  Public ID As Integer
  Public Value1 As Integer
  Public Value2 As Integer
  Public Sub New(ByVal ID As Integer, ByVal Value1 As Integer, B...続きを読む

Qint select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)について

見当違いな質問かもしれませんがお願いします。

複数のソケットを監視する際にselectを使う場合のことですが、
selectの動作と戻り値について疑問があります。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html
ここを参照すると、selectの戻り値は
「更新された 3 つのディスクリプタ集合に含まれているディスクリプタの数 (つまり、 readfds, writefds, exceptfds 中の 1 になっているビットの総数) を返す。」
とあります。
私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識だとreadfds,writefdsが引数として与えられているとしても、
どちらかのfd_setのうち、一つでも動きがあればselect文は
抜けてしまうことになります。とすると、戻り値として
「readfds, writefds, exceptfds 中の 1 になっているビットの総数」
は常に1ということになってしまいます。しかし、総数というからには
複数同時に1になることもあるはずです。

私の認識が間違っているとは思うのですが、どう間違っているのかわかりません。
select文の動きについて詳しく教えていただけないでしょうか。
または良いページがあれば教えてください。

見当違いな質問かもしれませんがお願いします。

複数のソケットを監視する際にselectを使う場合のことですが、
selectの動作と戻り値について疑問があります。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html
ここを参照すると、selectの戻り値は
「更新された 3 つのディスクリプタ集合に含まれているディスクリプタの数 (つまり、 readfds, writefds, exceptfds 中の 1 になっているビットの総数) を返す。」
とあります。
私の中でselectは登録してあるFDのうち、一つでも動きが...続きを読む

Aベストアンサー

>私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識はあっています。
しかし、selectを呼び出す以前にOKになっているFDがあれば、それらは全てビットがONになります。

話しを簡単にする為に、受信のみのソケットを3つ作成したとします。
これらの3つのソケットに向けて相手が電文を送ったとします。
その状態でまだ、こちらはselectを呼び出さずにいます。しばらくしてから、selectを呼び出すと、selectは即座にリターンし、3つのビットが一度にONになっているはずです。
一方、相手が、一切電文を送ってない状態で、selectを呼び出した場合は、何れかのビットがONになればリターンするので、そのときは、貴方が想像しているように
ビットの総数は1になる可能性が高いです。
従って、相手が電文を送る前にselectを呼び出すか、送った後にselectを呼び出すかは、その時のタイミングにより異なります。従って、ビット数の総和が常に1であるとは、考えない方が無難です。(1つのソケットしか使用しない場合は別ですが・・・)

>私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識はあっています。
しかし、selectを呼び出す以前にOKになっているFDがあれば、それらは全てビットがONになります。

話しを簡単にする為に、受信のみのソケットを3つ作成したとします。
これらの3つのソケットに向けて相手が電文を送ったとします。
その状態でまだ、こちらはselectを呼び出さずにいます。しばらくしてから、selectを呼び出すと、selectは即座にリターンし、3つのビ...続きを読む

QVBスクリプトの配列数字をJAVAスクリプトで使うには

表題があまり良くないですが
VBSでページを作っています

その中で
ページ閲覧者がテキストボックスに値を記入したときに
JAVAスクリプトのonchangeでJAVAスクリプトへ飛んで

VBスクリプトで定義した配列の値を代入したいのですが
うまくいきません
飛んでいった先のコードが
<script type="text/javascript">
<!--
//値の代入
function hoge(FRM){
FRM.hoge1.value=ここにVBスクリプトの配列
}
// -->
</script>
これだけのことなのですが
配列を直接数字で書くと
FRM.hoge1.value=<%=atai(1)%>
hoge1にはきちんと値が入力されます

しかし この1と言う数字の所に
FRM.hoge2.value の値をいれてやろうとすると
イメージとしては
FRM.hoge1.value=<%=atai(FRM.hoge2.value )%>
なんですが、これではエラーがでます(当然ですよね)
色々"" でくくったり & や + ()などの
組み合わせでやってもうまくいきません

どなたか正しい構文か方法を教えてください
よろしくお願いします


 

表題があまり良くないですが
VBSでページを作っています

その中で
ページ閲覧者がテキストボックスに値を記入したときに
JAVAスクリプトのonchangeでJAVAスクリプトへ飛んで

VBスクリプトで定義した配列の値を代入したいのですが
うまくいきません
飛んでいった先のコードが
<script type="text/javascript">
<!--
//値の代入
function hoge(FRM){
FRM.hoge1.value=ここにVBスクリプトの配列
}
// -->
</script>
これだけのことなのですが
配列を直接数字で書くと
FRM.hoge1.v...続きを読む

Aベストアンサー

何かを勘違いされていると思います。

umadura4747さんが言われている、VBScriptの配列と言うのは、サーバー上での変数を指し、JavaScriptの値と言うのは、クライアント上の変数を指しています。
つまり、次元が違うため実行できないのです。

解決方法としては、

1. VBScriptという配列がサーバー上でしか定義できない場合
 以下のようなJavaScriptのソースを生成するために、ASPコードを追加してあげる。

 var a = new Array("a", "b", "c");

2. クライアント側でも配列が定義できる場合
 先ほどと同じコードをあらかじめJavascriptで定義しておく

ASPとは、サーバー上で動的にHTMLソースを生成することを目的としています。
まずは、やりたいことをHTMLソースで記述し、それを生成するためには、どういったASPコードを書くかを考えてください。

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。


人気Q&Aランキング